【问题标题】:Trace/breakpoint trap during reallocation重新分配期间的跟踪/断点陷阱
【发布时间】:2022-01-02 11:00:15
【问题描述】:

我有一个一年前编写的图形代码现在不起作用(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-&gt;matrix[i] = realloc(gptr-&gt;matrix[i], gptr-&gt;size * sizeof(**gptr-&gt;matrix));,程序被异常Trace/breakpoint trap暂停。我用谷歌搜索了一段时间,对我来说,我的重新分配很可能有问题,但我不知道出了什么问题。此外,它在clang 甚至在线gcc 7.4 上都可以正常工作,而在我的gcc 8.1 上却无法成功。谁能看到我错在哪里?

【问题讨论】:

    标签: c graph dynamic-memory-allocation breakpoints realloc


    【解决方案1】:

    add_vertex 的第一个条目上,gptr-&gt;size == 8gptr-&gt;matrix 指向一个包含 8 个指向 malloc 内存的指针的数组。

    gptr->size++;
    

    现在gptr-&gt;size == 9

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

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

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

    由于gptr-&gt;size == 9,这会迭代9次,在第9次迭代时,垃圾指针gptr-&gt;matrix[8]被传递给realloc。不好。

    您可以改为迭代循环 gptr-&gt;size - 1 次,并分别初始化 gptr-&gt;matrix[gptr-&gt;size - 1] = malloc(...)。或者稍微懒一点,避免代码重复,你可以在这个循环之前初始化gptr-&gt;matrix[gptr-&gt;size - 1] = NULL,让它迭代gptr-&gt;size次,并依赖realloc(NULL, sz)等价于malloc(sz)的便利功能。

    【讨论】:

    • 没错,我几分钟前才发现它。重新分配的指针数组的最后一个元素从未分配过任何内存,因此我必须为最后一个元素应用malloc
    • 顺便说一句,将NULL 分配给重新分配数组的最后一个元素是一个有趣的想法,应该将其应用于更改:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 2022-01-05
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 2011-10-15
    相关资源
    最近更新 更多