Malloc'ing Arrays然后Free'ing他们?

T.G*_*all 5 c malloc pointers memory-management segmentation-fault

我正在搞乱c我在指针使用和语法区域有一些打嗝.

下面,我(尝试)创建一个指向整数数组的指针数组,然后将每个指针指向一个通过malloc()创建的数组.

创建数组后,然后循环遍历每个单元格,分配一个值.

现在,所有这些似乎都在起作用,但是当使用free()来取回内存时,程序崩溃了.

我注意到如果我在malloc()数组内存然后立即调用它们上的free(),程序执行没有问题.然而,当我malloc(),赋值和THEN调用free()时,将发生崩溃.(分段故障).

下面是有效的代码,malloc()然后立即free()ing

int (*ptrArr[5])[5];

for(int i=0; i<5; i++)
    ptrArr[i] = malloc(sizeof(int) * 5);

for(int i=0; i<5; i++)
    printf("ptrArr[%d][%x]->[%x]\n", i, &ptrArr[i], &*ptrArr[i]);
printf("\n");

for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);  
    }
    printf("\n");
}

for(int i=4; i>=0; i--)
    free(ptrArr[i]);
Run Code Online (Sandbox Code Playgroud)

上面按照我的预期执行,但是当我为单元格赋值然后尝试自由调用时,会生成一个分段错误:

int (*ptrArr[5])[5];

for(int i=0; i<5; i++)
    ptrArr[i] = malloc(sizeof(int) * 5);

for(int i=0; i<5; i++)
    printf("ptrArr[%d][%x]->[%x]\n", i, &ptrArr[i], &*ptrArr[i]);
printf("\n");

for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);  
    }
    printf("\n");
}

int loop = 5;
for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        *ptrArr[i][j] = (loop + (i*j));
        ++loop;
    }
}

printf("\n");
for(int i=0; i<5; i++){
    for(int j=0; j<5; j++){
        printf("[%x](%2d) | ", &*ptrArr[i][j], *ptrArr[i][j]);
    }
    printf("\n");
}

for(int i=4; i>=0; i--)
{
    printf("Freeing ptrArr[%x]\n", i);
    free(ptrArr[i]);
}
Run Code Online (Sandbox Code Playgroud)

我想我要么误解了

int (*ptrArr[5])[5];
Run Code Online (Sandbox Code Playgroud)

声明,我打算是一个5个指针的数组,每个指针指向一个整数数组,或者我没有正确地为单元格赋值,而是破坏导致free()失败的内存.

任何帮助将不胜感激,我希望这个问题清楚简洁.

谢谢.

use*_*109 2

我解决此类问题的方法是打印出sizeof各种嫌疑人,如下所示

int (*test[5])[5];

printf( "%zu ", sizeof(test) );
printf( "%zu ", sizeof(test[0]) );
printf( "%zu\n", sizeof(test[0][0]) );
Run Code Online (Sandbox Code Playgroud)

结果是40 8 20。(请注意,在我的机器上,anint是 4 个字节,指针是 8 个字节。)
这告诉我这test是一个由 5 个指针组成的数组。从逻辑上讲,这test[0]是一个单一的指针。但有趣的是,这test[0][0]是一个由 5 个整数组成的数组。

如果我添加以下代码行

printf( "%zu\n", sizeof(test[0][0][0]) );
Run Code Online (Sandbox Code Playgroud)

输出是 4,即test[0][0][0]是一个int。由此我们得出结论,该声明int (*test[5])[5]正在声明一个三维数组,这不是您想要的。


所以让我们尝试一个更简单的声明,就像这样

int (*test)[5];

printf( "%zu ", sizeof(test) );
printf( "%zu ", sizeof(test[0]) );
printf( "%zu\n", sizeof(test[0][0]) );
Run Code Online (Sandbox Code Playgroud)

输出是8 20 4,也就是说,它test是一个指针,test[0]是一个 5 个整数的数组,并且test[0][0]是一个int。我们得出结论,int (*test)[5]声明了一个二维数组。


下一个问题是我们如何为数组分配内存。如果我们这样做

test = malloc( 5 * sizeof(int) );
Run Code Online (Sandbox Code Playgroud)

那么我们有一个 1 行 5 列的数组,基本上是一个一维数组。

要获得包含行的二维数组N,我们需要

test = malloc( N * 5 * sizeof(int) );
Run Code Online (Sandbox Code Playgroud)

然后我们可以像这样填充、打印和释放数组

int N = 5;
for ( int row = 0; row < N; row++ )
    for ( int col = 0; col < 5; col++ )
        test[row][col] = (row+5)*10 + col;

for ( int row = 0; row < N; row++ )
{
    for ( int col = 0; col < 5; col++ )
        printf( "%2d ", test[row][col] );
    printf( "\n" );
}

free( test );
Run Code Online (Sandbox Code Playgroud)