Trace/breakpoint 重新分配时陷入陷阱

Trace/breakpoint trap during reallocation

我有一个一年前写的图表代码,现在不能用了(AFAIR 它能用)。该图是用分别与对角线对称的方阵实现的。我省略了很多代码以使其尽可能清晰,这仍然足以使错误持续存在。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

typedef struct
{
    int **matrix;
    unsigned size;
} graph;


void init(graph *gptr, int *matrix[], unsigned size)
{
    gptr->size = size;
    gptr->matrix = malloc(gptr->size * sizeof(*gptr->matrix));
    for (unsigned i = 0; i < gptr->size; i++)
        gptr->matrix[i] = malloc(gptr->size * sizeof(**gptr->matrix));
    
    for (unsigned i = 0; i < gptr->size; i++)
        for (unsigned j = 0; j <= i; j++)
            gptr->matrix[i][j] = gptr->matrix[j][i] = matrix[i][j];
}


void add_vertex(graph *gptr, unsigned vertex)
{
    for (unsigned i = 1; i < gptr->size; i++)
        if (gptr->matrix[i][0] == vertex) return;
    
    gptr->size++;
    gptr->matrix = realloc(gptr->matrix, gptr->size * sizeof(*gptr->matrix));
    for (unsigned i = 0; i < gptr->size; i++)
        /* ERROR */
        gptr->matrix[i] = realloc(gptr->matrix[i], gptr->size * sizeof(**gptr->matrix));
    
    gptr->matrix[gptr->size - 1][0] = gptr->matrix[0][gptr->size - 1] = vertex;
    for (unsigned i = 1; i < gptr->size; i++)
        gptr->matrix[gptr->size - 1][i] = gptr->matrix[i][gptr->size - 1] = -1;
}


#define EDGES 7
#define RANDOM(min, max) min + rand() / ((RAND_MAX - 1) / (max - min))
#define MIN -1
#define MAX 9

int **getMatrix(unsigned size)
{
    int **matrix = malloc(size * sizeof(*matrix));
    for (unsigned i = 0; i < size; i++)
    {
        matrix[i] = malloc((i + 1) * sizeof(**matrix));
        matrix[i][0] = i;
    }
    
    for (unsigned i = 1; i < size; i++)
    {
        for (unsigned j = 1; j < i; j++)
            do
                matrix[i][j] = RANDOM(MIN, MAX);
            while (!matrix[i][j]);
        matrix[i][i] = rand() % 2 - 1;
    }

    return matrix;
}


int main(void)
{
    int **matrix = getMatrix(EDGES + 1);
    
    graph x;
    init(&x, matrix, EDGES + 1);

    add_vertex(&x, EDGES + 1);
}

gptr->matrix[i] = realloc(gptr->matrix[i], gptr->size * sizeof(**gptr->matrix)); 处,程序因异常 Trace/breakpoint trap 暂停。我用谷歌搜索了一段时间,对我来说很可能是我的重新分配出了问题,但我不知道出了什么问题。此外,它在 clang 甚至在线 gcc 7.4 上运行良好,而在我的 gcc 8.1 上却无法成功。谁能看出我错在哪里?

add_vertex 的第一个条目上,gptr->size == 8gptr->matrix 指向一个由 8 个指向 malloc 内存的指针组成的数组。

gptr->size++;

现在gptr->size == 9.

    gptr->matrix = realloc(gptr->matrix, gptr->size * sizeof(*gptr->matrix));

现在gptr->matrix指向一个9指针数组。 gptr->matrix[0] .. gptr->matrix[7] 是之前有效的 malloc'ed 指针,gptr->matrix[8] 包含未初始化的垃圾。

for (unsigned i = 0; i < gptr->size; i++)
    /* ERROR */
    gptr->matrix[i] = realloc(gptr->matrix[i], gptr->size * sizeof(**gptr->matrix));

gptr->size == 9开始,迭代9次,在第9次迭代时,垃圾指针gptr->matrix[8]被传递给realloc。不好。

您可以将循环迭代 gptr->size - 1 次,然后单独初始化 gptr->matrix[gptr->size - 1] = malloc(...)。或者为了有点懒惰并避免代码重复,你可以在这个循环之前初始化 gptr->matrix[gptr->size - 1] = NULL ,让它迭代 gptr->size 次,并依赖 realloc(NULL, sz) 等同于 malloc(sz).