0

我正在尝试编写一个函数来创建一个连续的内存块并将其分配给一个 3d 数组。该代码的工作原理是它允许我使用内存,并且当我使用存储在使用此函数创建的对象中的数据时,结果看起来是正确的。但是,当我尝试释放使用此函数分配的内存时,我立即收到 glibc 错误。这是功能:

void *** matrix3d(int size, int rows, int cols, int depth) {
    void ***result;

    int col_size = depth * size;
    int row_size = (sizeof(void *) + col_size) * cols;
    int data_size = (rows * cols * depth + 1) * size;
    int pointer_size = rows * sizeof(void **) + cols * sizeof(void *);
    int i, j;
    char *pdata, *pdata2;

    if((result = (void ***) malloc(pointer_size + data_size)) == NULL)
            nerror("ERROR: Memory error.\nNot enough memory available.\n", 1);

    pdata = (char *) result + rows * sizeof(void **);

    if((long) pdata % (col_size + sizeof(void *)))
            pdata += col_size + sizeof(void *) - (long) pdata % (col_size + sizeof(void *));

    for(i = 0; i < rows; i++) {
            result[i] = pdata;

            pdata2 = pdata + cols * sizeof(void *);

            for(j = 0; j < cols; j++) {
                    result[i][j] = pdata2;
                    pdata2 += col_size;
            }

            pdata += row_size;
    }

    return result;
}

它以这种方式调用:

double ***positions = (double ***) matrix3d(sizeof(double), numResidues, numChains, numTimesteps);

for(i = 0; i < numResidues; i++)
    for(j = 0; j < numChains; j++)
        for(k = 0; k < numTimesteps; k++)
             positions[i][j][k] = 3.2;

free(positions);

我做错了什么?感谢您的帮助。

4

4 回答 4

3

我做错了什么?

你的代码很难理解(你玩pdata了很多),但 99% 的你都在写超出分配的空间,而且你弄乱了 glibc 留下的簿记。

我可以很好地使用我写的数据。唯一的问题是当我尝试免费使用时。

那是因为glibc只有在你打电话时才有机会看到你搞砸了。

于 2012-08-15T06:35:35.997 回答
1

请原谅我亲爱的莎莉阿姨。

int data_size = (rows * cols * depth + 1) * size;

这应该是:

int data_size = (rows * cols * (depth + 1)) * size;

运行下面的代码valgrind立即发现了错误。

于 2012-08-15T06:53:06.380 回答
0

您正在做的是一次分配,然后将其转换为三指针,这意味着您必须处理很多偏移量。

更多的分配可能会更好:

char ***result = malloc(sizeof(char **) * rows);

for(i = 0; i < rows; i++) {
    result[i] = malloc(sizeof(char *) * cols);

    for(j = 0; j < cols; j++) {
        result[i][j] = malloc(sizeof(char) * size);

        /* Copy data to `result[i][j]` */
    }
}

释放时,您必须释放所有分配:

for(i = 0; i < rows; i++) {
    for(j = 0; j < cols; j++) {
        free(result[i][j]);
    }

    free(result[i]);
}

free(result);
于 2012-08-15T06:44:09.147 回答
0

像这样的事情是错误的伟大候选人

pdata = (char *) result + rows * sizeof(void **);

完全没有理由规避编译器为您执行的地址计算。

于 2012-08-15T07:00:28.940 回答