指针(?)使C程序崩溃

时间:2014-07-19 12:43:26

标签: c pointers

我尝试为动态" MapNode"数组使用新结构,但程序崩溃了:

  

Astar.exe中0x000C191C处的未处理异常:0xC0000005:访问冲突读取位置0xCCCCCCCC。

我调用getConnectedNodesArray函数,该函数调用另外两个函数。 我知道这是一些指针问题。 当我使用数据的副本而不是试图指向MapNode map [] [12]中的现有数据时,它可以工作。

感谢。

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;
}

3 个答案:

答案 0 :(得分:2)

你似乎害怕间接。面对它,确保你得到你想要的数量:

typedef struct MapNode * MapNodePointer;

以上是一个坏主意,因为它隐藏了指针。

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

上述结构不适合存储指向节点的动态列表。 nodes - 成员需要另外一位明星:MapNode** nodes;

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

有一种更好的方式来指示所需的内存量:arr->size * sizeof *arr->nodes始终检查分配失败。裸骨将会中止该计划。在此插入:

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

编译器现在会正确地抱怨下一行,只需删除运营商地址:

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

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

上述行可以替换为MapNode* first = 0;

    MapNodesArray temp = { first, 0 };

上面的行定义了一个自动变量,永远不会返回指向它的指针。

    return &temp;
}

糟糕。完成重写:

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

甚至更好:

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

答案 1 :(得分:1)

你认为多少内存

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

会分配吗? (提示:完全没有。)

此外,您还会返回指向局部变量的指针(通过&temp)。那个东西因函数返回而死。

答案 2 :(得分:0)

同意EOF的说法,也就是

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

在函数addNodeToEnd中,将地址p写入nodes数组之外的内存位置。这将导致内存损坏。

来说明 说变量'节点'有一个内存地址0x00000002,并通过调用realloc分配了一个内存位置,如0x00000050。上面的语句从0x00000002获取偏移量(arr-> size-1),而不是从0x00000050获取。这是因为您使用&来获取节点的地址。形式的东西

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

将从0x00000050获取偏移,这是您似乎需要的。