This question already has an answer here:
Closed 11 months ago.
Dynamic memory access only works inside function
(1个答案)
我的代码有一些问题,问题是我没有真正得到SEG错误,我可以运行它,也可以得到良好的结果,但当我使用valgrind时,我得到一些内存泄漏错误,如:
==2265== Invalid read of size 4
==2265==    at 0x109A3B: move (in /home/cosmi/Desktop/315CA_CojocaruCosmin_Tema3/snowfight)
==2265==    by 0x10B419: main (in /home/cosmi/Desktop/315CA_CojocaruCosmin_Tema3/snowfight)

==2265==  Address 0x55ccb88 is 8 bytes inside a block of size 20 free'd

==2265==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==2265==    by 0x10A0F6: meltdown (in /home/cosmi/Desktop/315CA_CojocaruCosmin_Tema3/snowfight)

==2265==    by 0x10B4A9: main (in /home/cosmi/Desktop/315CA_CojocaruCosmin_Tema3/snowfight)

==2265==  Block was alloc'd at
==2265==    at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2265==    by 0x10AFE9: main (in /home/cosmi/Desktop/315CA_CojocaruCosmin_Tema3/snowfight)

问题是,我将main()中分配的两个矩阵(带有calloc)传递给名为meltdown()的函数。在这个函数中,我应该调整这两个列的大小,去掉第一列和最后一列。所以从一个5x5我应该得到一个3x3矩阵。我不知道如何使用realloc实现这一点,所以我使用另外两个矩阵将元素复制到其中,然后使初始矩阵指针指向这两个。。
int main() {
    int **a = calloc((2 * R + 1) , sizeof(int*));

    int **b = calloc((2 * R + 1) , sizeof(int*));

    for (i = 0; i < (2 * R + 1); i++) {
        a[i] = calloc((2 * R + 1) , sizeof(int));
        b[i] = calloc((2 * R + 1) , sizeof(int));
    }
}

void meltdown(int **a, int **b, int R, ..) {
    int n = 2 * R + 1;
    int **c = malloc((n - 2) * sizeof(int*));
    for(i = 0; i < n - 2; i++)
        c[i] = malloc((n-2)*sizeof(int));
    l = 0;
    for(i = 1; i < n - 1; i++) {
        k = 0;
        for(j = 1; j < n - 1; j++) {
            c[l][k] = a[i][j];
            k++;
        }
        l++;
    }
    for(i = 0; i < n; i++)
        free(a[i]);
    free(a);
    a = c;
   //same goes for b
}

实际上,我很沮丧,因为我的代码在实际问题上似乎工作得很好,并且很好地解决了问题,但是由于这个内存泄漏问题,我得了0分。

最佳答案

a = c在内部分配局部变量,它不会影响调用方的变量。如果meltdown()试图使用其main()指针,它将访问由a释放的内存,从而导致未定义的行为。
如果free(a);应该更新调用者的变量,则需要传递一个指向该变量的指针,并在meltdown()中取消对该变量的引用。

void meltdown(int ***aptr, int ***bptr, int R) {
    int **a = *aptr;
    int **b = *bptr;
    int n = 2 * R + 1;
    int **c = malloc((n - 2) * sizeof(int*));
    for(i = 0; i < n - 2; i++)
        c[i] = malloc((n-2)*sizeof(int));
    l = 0;
    for(i = 1; i < n - 1; i++) {
        k = 0;
        for(j = 1; j < n - 1; j++) {
            c[l][k] = a[i][j];
            k++;
        }
        l++;
    }
    for(i = 0; i < n; i++)
        free(a[i]);
    free(a);
    *aptr = c;
   //same goes for b
}

当您调用函数时,必须获取地址:
meltdown(&a, &b, R);

10-06 05:08