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.