简体   繁体   中英

Pointers(?) crash the C program

I try to use a new struct for a dynamic "MapNode"s array, yet the program crashes:

Unhandled exception at 0x000C191C in Astar.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC.

I call the getConnectedNodesArray function, which calls the other two functions. I know it's some kind of pointers problem. When I used copies of the data instead of trying to point to existing data in MapNode map[][12] it worked.

Thanks.

typedef struct MapNode * MapNodePointer;


typedef struct MapNode{
    int x;
    int y;
    int value;
    int traversable;
    double f;
    double g;
    double h;
    MapNodePointer parentNode;
}MapNode;


typedef struct MapNodesArray{
    MapNode* nodes;
    int size;
}MapNodesArray;

void addNodeToEnd(MapNodesArray* arr, MapNode* p) {
    arr->size++;
    arr->nodes = realloc(arr->nodes, arr->size * sizeof(MapNode*));
    (&(arr->nodes))[arr->size - 1] = p;
}

MapNodesArray* NewNodesArr() {
    MapNode *first = realloc(NULL, 0 * sizeof(MapNode));
    MapNodesArray temp = { first, 0 };
    return &temp;
}

MapNodesArray* getConnectedNodesArray(MapNodePointer node, MapNode map[][12]) {
    MapNodesArray* arr = NewNodesArr();
    addNodeToEnd(&arr, &map[node->x - 1][node->y - 1]);
    return arr;
}

You seem to fear indirection. Face it head-on and make sure you get exactly the amount you want:

typedef struct MapNode * MapNodePointer;

The above is a bad idea, because it hides the pointer-ness.

typedef struct MapNodesArray{
    MapNode* nodes;
    int size;
}MapNodesArray;

The above structure is no good for storing a dynmaic list of pointers to nodes. The nodes -member needs one more star: MapNode** nodes;

void addNodeToEnd(MapNodesArray* arr, MapNode* p) {
    arr->size++;
    arr->nodes = realloc(arr->nodes, arr->size * sizeof(MapNode*));

There's a better way to indicate the amount of memory you need: arr->size * sizeof *arr->nodes Always check for allocation failure. Bare-bones would be aborting the program. Insert here:

    if(!arr->nodes) abort();

The compiler will rightfully complain about the next line now, just remove the address-of-operator:

    (&(arr->nodes))[arr->size - 1] = p;
}

MapNodesArray* NewNodesArr() {
    MapNode *first = realloc(NULL, 0 * sizeof(MapNode));

The above line could be replaced with MapNode* first = 0;

    MapNodesArray temp = { first, 0 };

The above line defines an automatic variable, never return a pointer to that.

    return &temp;
}

oops. Complete rewrite:

MapNodesArray* NewNodesArr() {
    MapNodesArray temp* = malloc(sizeof *temp);
    *temp = (MapNodesArray){ 0, 0 };
    return temp;
}

Or even better:

MapNodesArray NewNodesArr() {
    return (MapNodesArray){ 0, 0 };
}

Exactly how much memory do you think

MapNodesArray* NewNodesArr() {
    MapNode *first = realloc(NULL, 0 * sizeof(MapNode));
    MapNodesArray temp = { first, 0 };
    return &temp;
}

will allocate? (hint: none at all.)

Also, you're returning a pointer to a local variable (via &temp ). That thing dies with the function return.

Agree with what EOF has said, also the line

(&(arr->nodes))[arr->size - 1] = p;

in function addNodeToEnd, will be writing the address p in a memory location outside the the nodes array. This will lead to memory corruption.

to illustrate say variable 'nodes' has a memory address 0x00000002 and you have assigned a memory location say 0x00000050 through the call to realloc. The statement above takes the offset (arr->size-1) from 0x00000002 instead of taking it from 0x00000050. This is because you are taking the address of nodes by using &. Something of the form

(arr->nodes)[arr->size - 1] = p;

will take the offset from 0x00000050 which is what you seem to be needing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM