Declaring a global structure causes a segmentation fault but when localized it is fine? [duplicate]

问题内容:

As the title suggests, when I declare structure BasicSetup_S globally, I get a segmentation fault. But if I move BasicSetup_S into CallFunction() the segmentation fault goes away.

The output is correct each time. It produces exactly what I expect to see but I get the segmentation fault. But, if I move the BasicSetup_S structure inside CallFunction the segmentation fault goes away. Is there any reason why?

I’m thinking that my entire program may use too much memory causing a fault when I declare more global variables.

For ease of reading, I simplified the names of everything and showed only the useful parts of the code

#include <stdio.h>
#include "stdint.h"

typedef struct BasicSetup
{
    uint16_t A;
    uint16_t B;
    uint16_t C;
    uint16_t D;
    uint16_t E;
    uint16_t F[3];
    uint16_t G[7];
}BasicSetup;

BasicSetup BasicSetup_S = {
    // A,               // B,
    1,                  2,
    // C,               // D,
    3,                  4,
    // E,               // F[2],[1],[0]
    5,                    6 , 7 , 8,
    // G[6],[5],[4],[3],[2],[1],[0]
    9 , 10, 11, 12, 13, 14, 15,
};

void CallFunction(uint8_t *writeBuffer, int begAddress, int endAddress)
{
    int i;
    uint16_t tempVal;
    int StartingPoint = 0;

    for (i = begAddress; i < endAddress; i++)
    {
        // Grabs information from Device Information Structure
        if (i >= 0 && i <= 7)
        {
            // Grab Value
            tempVal = *((uint16_t*)&BasicSetup_S.A + i);
            // Send Value
            writeBuffer[(StartingPoint)++] = tempVal & 0xFF;
        }
        else if (i >= 13 && i <= 19)
        {
            // Grab Value
            tempVal = *((uint16_t*)&BasicSetup_S.G + i - 13);
            // Send Value
            writeBuffer[(StartingPoint)++] = tempVal & 0xFF;
        }
    }

    return;
}

int main(int argc, char *argv[]) {
    int numOfBytes = 0;
    int i = 0;
    uint8_t writeBuffer[256];

    CallFunction(writeBuffer, 0, 8);
    for (i = 0; i < 8; i++) printf("%d, ", writeBuffer[i]);
    printf("\n");

    CallFunction(writeBuffer, 13, 19);
    for (i = 0; i < 6; i++) printf("%d, ", writeBuffer[i]);
    printf("\n");

    CallFunction(writeBuffer, 19, 20);
    for (i = 0; i < 1; i++) printf("%d, ", writeBuffer[i]);
    printf("\n");

    return 0;
}

问题评论:

    
Show us the calls please.
    
The problem is you’re accessing an array out of bounds.
3  
Also, the order in which you think the array members F and G are initialized is wrong.
1  
@Rayaarito C doesn’t work like that. The behaviour is undefined for the same reasons as outlined in the duplicate.
1  
Also could you actually consider producing a Minimal, Complete, and Verifiable example. Because this is not one.

答案:

答案1:

The behaviour of your code is undefined.

You cannot use pointer arithmetic (of non-unsigned char type) to reach other scalar members in a struct. For staters, you are assuming there is no padding between the members.

Why not use a single array instead?

typedef struct BasicSetup
{
    uint16_t m[15];
} BasicSetup;

The C standard insists that the array data are contiguous, and pointer arithmetic is then perfectly well-defined.

答案评论:

    
“You cannot use pointer arithmetic to reach other scalar members in a struct” Sure you can, this is perfectly fine, although there might be padding anywhere. There is no UB, given that all access is aligned.
    
@Lundin. No, you can’t. You can take the address of a scalar, or set a pointer one beyond it. But you can’t dereference a pointer obtained in the latter manner. What makes you think otherwise?
    
@Lundin not again. Of course there is UB because the standard says so.
    
Bathsheba is right, @Lundin. Pointer arithmetic is defined only within the array into which the pointer points, with scalars treated as one-element arrays, and with the exception that a pointer to the element just past the end of the array can be computed (but not dereferenced).
    
What I mean is this for(uint8_t* ptr = (uint8_t*)&my_struct; ptr < (uint8_t*)&my_struct + sizeof(my_struct); ptr++), which is supported by normative 6.3.2/7: “When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.” This, assuming uint8_t counts as a character type.

原文地址:

https://stackoverflow.com/questions/47754608/declaring-a-global-structure-causes-a-segmentation-fault-but-when-localized-it-i

添加评论