【问题标题】:Realloc and SIGABRTRealloc 和 SIGABRT
【发布时间】:2018-01-13 14:47:13
【问题描述】:

我正在编写一个程序来发现从一个顶点到另一个顶点的最佳路径。好吧,我创建顶点,为邻居列表分配内存。当我在两个顶点之间创建连接时,我会重新分配列表的内存以向邻居列表中再添加一个顶点。它似乎在前两次有效,但在第三次它崩溃并给我信号“SIGABRT”。我在任何论坛中都找不到该问题的解决方案。这是我的代码:

typedef struct vertex{
    char* name;
    Vertex** neighbors;
    float x, y;
}Vertex;

Vertex* create_vertex(char* name, float x, float y){
    Vertex* vertex = (Vertex*) malloc(sizeof(Vertex));
    vertex->x = x;
    vertex->y = y;
    vertex->name = (char*) malloc(sizeof(char)*strlen(name) + 1);
    strcpy(vertex->name, name);
    vertex->neighbors = (Vertex**) malloc(sizeof(Vertex*));
    vertex->neighbors[0] = NULL;

return vertex;
}

void creates_connection(Vertex* v1, Vertex* v2){
    if(areNeighbors(v1, v2)){
        printf("Vertices ja sao vizinhos");
        return;
    }

    Vertex** real;

    if(v1->neighbors[0] == NULL){
        real = (Vertex**) realloc(v1->neighbors, sizeof(Vertex*)+1);

        if(real != NULL){
            v1->neighbors = real;
            v1->neighbors[0] = v2;
            v1->neighbors[1] = NULL;
        }else printf("Nao foi possivel realocar memoria");

    }else{
        Vertex* aux = v1->neighbors[0];
        int i = 0;

        while(aux != NULL){
            aux = v1->neighbors[i];
            i++;
        }

        real= (Vertex**) realloc(v1->neighbors, (sizeof(Vertex*))*(i+1));

        if(real!= NULL){
            v1->neighbors= real;
            v1->neighbors[i] = v2;
            v1->neighbors[i+1] = NULL;
        }else printf("Nao foi possivel realocar memoria");
    }

    if(v2->neighbors[0] == NULL){
        real = (Vertex**) realloc(v2->neighbors, sizeof(Vertex*));

        if(real != NULL){
            v2->neighbors = realocado;
            v2->neighbors[0] = v1;
            v2->neighbors[1] = NULL;
        }

    }else{
        Vertex* aux = v2->neighbors[0];
        int i = 0;

        while(aux != NULL){
            aux = v2->neighbors[i];
            i++;
        }

        //HERE, BELLOW, IT CRASHES, DOESN'T PASS TO THE IF
        real = (Vertex**) realloc(v2->neighbors, (sizeof(Vertex*))*(i+1));

        if(real != NULL){
            v2->neighbors = real;
            v2->neighbors[i] = v1;
            v2->neighbors[i+1] = NULL;
        }else printf("Nao foi possivel realcoar memoria");

    }
}

我不知道这是否是做我想做的事情的最佳方式,我接受建议,但我也想了解发生了什么,我的意思是,为什么会发生这个 SIGABRT。

【问题讨论】:

  • real = (Vertex**) realloc(v1->neighbors, sizeof(Vertex*)+1); 应该是 -->> real = (Vertex**) realloc(v1->neighbors, sizeof(Vertex*)*2);
  • Vertex 是如何定义的?
  • 这肯定是错误的realloc(v1->neighbors, sizeof(Vertex*)+1); 通常看起来像realloc(v1->neighbors, (current_size+1) * sizeof(Vertex*)); 我也认为类型错误
  • 顶点是一种抽象数据类型,它包含两个变量float和一个变量char*。我想我可以看到错误,“+1”只会在内存重新分配中添加一个字节,对吧?
  • @yamunaq - 是的,这肯定是一个错误。但我认为还有更多的问题。要获得帮助,请发布Vertex的代码

标签: c realloc


【解决方案1】:
  • 您可以跟踪(使用的)大小,而不是指针数组末尾的 NULL 标记
  • 不要在每次添加时重新分配,使用更大的增量
  • 如果第一个参数为 NULL,realloc() 就像 malloc() 一样工作
  • 集中您的(重新)分配,这将集中您的错误
  • 将内联静态函数(在某些优化级别)

#include <stdlib.h>

struct vertex{
    char* name;
    float x, y;
    unsigned size, used;
    struct vertex **neighbors;
    };

struct vertex *create_vertex(char* name, float x, float y){
    struct vertex *vv = malloc(sizeof *vv );

    vv->x = x;
    vv->y = y;
    vv->name = strdup(name);
    vv->size=0;
    vv->used=0;
    vv->neighbors = NULL;

return vv;
}

static void resize_vertex(struct vertex *pp, unsigned newsize)
{
struct vertex **tmp;

if (!newsize)newsize =4;
tmp = realloc(pp->neighbors, newsize * sizeof *pp->neighbors );
if(!tmp) { /* handlefailure */ }

pp->neighbors = tmp;
pp->size = newsize;
}


void creates_connection(struct vertex* v1, struct vertex* v2){
    if(areNeighbors(v1, v2)){
        printf("Vertices ja sao vizinhos");
        return;
    }

    if(v1->used== v1->size) resize_vertex(v1, 2*v1->size);
    v1->neighbors[v1->used] = v2;
    v1->used += 1;

return;
}

【讨论】:

  • 不需要缩进,因为没有任何嵌套块;-)
【解决方案2】:

此答案侧重于指出已发布代码中的(某些)问题。最后,此答案包含对适用于您当前设计的代码更改的建议。如果您愿意重新设计,请查看@wildplasser 的答案

这里有问题

if(v1->neighbors[0] == NULL){
    real = (Vertex**) realloc(v1->neighbors, sizeof(Vertex*)+1);
                                                           ^^^^
                                               This only increase with 1 byte
                                               but you want 1 pointer

这里

if(v2->neighbors[0] == NULL){
    real = (Vertex**) realloc(v2->neighbors, sizeof(Vertex*));
                                                        ^^^^
                                               No increase at all

这里还有一个问题:

    Vertex* aux = v1->neighbors[0];
    int i = 0;

    while(aux != NULL){
        aux = v1->neighbors[i];
        i++;
    }

    real= (Vertex**) realloc(v1->neighbors, (sizeof(Vertex*))*(i+1));

由于您的设计要求数组末尾始终有一个 NULL 指针,因此您需要让 i 从 1 开始,即

    int i = 1;

当您写出分配的内存时,这部分也有问题 - 请记住索引从零开始:

    real= (Vertex**) realloc(v1->neighbors, (sizeof(Vertex*))*(i+1));

    if(real!= NULL){
        v1->neighbors= real;
        v1->neighbors[i] = v2;
        v1->neighbors[i+1] = NULL;  // UPS... write outside allocated memory
                                    // Writing to [i+1] requires that you
                                    // have i+2 pointers but you only
                                    // have i+1

有趣的是,当第一个指针为NULL 时,您不需要处理这两种特殊情况。 else中的代码也可以处理第一个指针为NULL的情况。

所以这段代码:

if(v1->neighbors[0] == NULL){
    real = (Vertex**) realloc(v1->neighbors, sizeof(Vertex*)+1);

    if(real != NULL){
        v1->neighbors = real;
        v1->neighbors[0] = v2;
        v1->neighbors[1] = NULL;
    }else printf("Nao foi possivel realocar memoria");

}else{
    Vertex* aux = v1->neighbors[0];
    int i = 0;

    while(aux != NULL){
        aux = v1->neighbors[i];
        i++;
    }

    real= (Vertex**) realloc(v1->neighbors, (sizeof(Vertex*))*(i+1));

    if(real!= NULL){
        v1->neighbors= real;
        v1->neighbors[i] = v2;
        v1->neighbors[i+1] = NULL;
    }else printf("Nao foi possivel realocar memoria");
}

可以简化为

    Vertex* aux = v1->neighbors[0];
    int i = 1;         // NOTICE: Use 1 instead of 0

    while(aux != NULL){
        aux = v1->neighbors[i];
        i++;
    }

    real= (Vertex**) realloc(v1->neighbors, (sizeof(Vertex*))*(i+1));

    if(real!= NULL){
        v1->neighbors= real;
        v1->neighbors[i-1] = v2;   // NOTICE: i-1
        v1->neighbors[i] = NULL;   // NOTICE: i
    }else printf("Nao foi possivel realocar memoria");

这也适用于您处理 v2 的第二个块

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 2012-01-25
    • 2014-01-31
    • 2015-01-04
    • 2018-08-29
    相关资源
    最近更新 更多