在C中创建***对象(指向指针的指针)

时间:2012-08-15 06:31:26

标签: c linux pointers

我正在尝试编写一个函数来创建一个连续的内存块并将其分配给一个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 个答案:

答案 0 :(得分:3)

  

我做错了什么?

您的代码难以理解(您经常使用pdata),但99%您正在写过分配的空间而且您正在搞乱glibc留下的簿记。

  

我可以使用我写的数据就好了。唯一的问题是我   尽量使用免费。

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

答案 1 :(得分:1)

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

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

这应该是:

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

valgrind下运行代码会立即识别错误。

答案 2 :(得分: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);

答案 3 :(得分:0)

像这样的事情是出错的重要候选人

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

根本没有理由绕过编译器为你做的地址计算。