C - 释放数组内的指针

时间:2013-12-12 02:40:31

标签: c arrays pointers memory free

我一直试图让我的所有指针都使用malloc来初始化为指针数组(或指针指针),这样我就可以通过该数组并释放每个指针像free一样的东西(ptr_array [i]);而不必单独释放每一个。

我相信这是可能的,但是我的代码有些麻烦,因为应该释放所有东西的功能(如果可能的话,我宁愿将它全部保存在一个单独的函数中)显然无法正常编辑“子指针”,似乎它们被复制而不像“主指针”。

这是代码,让我难过:

#include <stdlib.h>
#include <stdio.h>

void free_test(int** arg){
    printf("\tReceived arg addr: %p\n",arg);
    printf("\tFreeing arg[0] = %p\n",arg[0]);
    //And, just to MAKE SURE that arg[0] is ver, we do this:
    printf("\tIn-function ver[0] = %d\n",arg[0][0]);
    arg[0][0] = 2;
    printf("\tIn-function ver[0] = %d\n",arg[0][0]);

    free(arg[0]); //This one doesn't work...
    free(arg); //This one works though.
}

int main(){
    int** var;
    int* ver;
    int i;
    printf("ver addr 1: %p\n", ver);
    ver = malloc( sizeof(int) * 3 );
    printf("ver addr 2: %p\n", ver);
    for(i=0;i<3;i++){
        ver[i] = 5*i;
    }
    for(i=0;i<3;i++){
        printf("ver[%d]: %d\t(@ %p)\n",i,ver[i],&(ver[i]));
    }
    printf("var addr 1: %p\n", var);
    var = malloc( sizeof(int *) );
    printf("var addr 2: %p\n", var);
    var[0] = ver;
    printf("var[0] addr = %p\n", var[0]);
    free_test(var);
    printf("ver[0] new value: %d\n", ver[0]);
    //free(var); (free(arg) works in the function, so this one throws an error.)
    printf("So far so good, now break.\n");
    free(ver);
    printf("Didn't break. :(\n");
    return 0;
}

这是它目前给我的输出:

ver addr 1: 0x8048679
ver addr 2: 0x8b0f008
ver[0]: 0   (@ 0x8b0f008)
ver[1]: 5   (@ 0x8b0f00c)
ver[2]: 10  (@ 0x8b0f010)
var addr 1: 0xad7ff4
var addr 2: 0x8b0f018
var[0] addr = 0x8b0f008
    Received arg addr: 0x8b0f018
    Freeing arg[0] = 0x8b0f008
    In-function ver[0] = 0
    In-function ver[0] = 2
ver[0] new value: 0
So far so good, now break.
Didn't break. :(

我对C不太好,所以任何帮助都会受到赞赏。特别是因为ver [0]的值在函数内部被改变,但不在外部,我猜这将与为什么free(...)也不起作用有关。

提前致谢。

4 个答案:

答案 0 :(得分:1)

我对C的了解正在消退,但IIRC后续内存free会导致未定义的行为。因此,您无法保证能够发现任何错误。如果我理解正确,行为将根据特定的操作系统,编译器和stdlib实现(甚至特定的程序运行)而变化很大。

P.S。我的VS2012 VC ++编译器在free(ver);上完全中断。输出是:

ver addr 1: CCCCCCCC
ver addr 2: 00B8AFF0
ver[0]: 0       (@ 00B8AFF0)
ver[1]: 5       (@ 00B8AFF4)
ver[2]: 10      (@ 00B8AFF8)
var addr 1: CCCCCCCC
var addr 2: 00B85BF0
var[0] addr = 00B8AFF0
        Received arg addr: 00B85BF0
        Freeing arg[0] = 00B8AFF0
        In-function ver[0] = 0
        In-function ver[0] = 2
ver[0] new value: -17891602
So far so good, now break.

答案 1 :(得分:1)

我已经在gcc 4.6.3上测试了你的代码,发现这个程序使用valgrind没有任何内存泄漏。当我在main中删除“free(ver)”行时,程序运行完美,也没有任何内存泄漏。我认为free_test例程已成功释放了你在main中的那两个malloc。至于为什么在程序中再次释放var时没有任何coredump弹出,这取决于不同的操作系统实现。

使用valgrind进行测试,如果你想检查涉及malloc和free的内存泄漏,你会发现它很有用。

答案 2 :(得分:0)

使用

&#34; *(*(arg + 0)+0)&#34;

而不是[] []。 像[] [] ... []这样的语法只能解除引用指针一次。每个[]只改变指针的语义(当+1时它跳转的位置),与取消引用时间无关。


void free_test(int** arg){
printf("\tReceived arg addr: %p\n",arg);
    printf("\tFreeing arg[0] = %p\n",arg[0]);
    //And, just to MAKE SURE that arg[0] is ver, we do this:
    printf("\tIn-function ver[0] = %d\n",arg[0][0]);
    arg[0][0] = 2;
//  ^^^^^^^^^^^^^^ here, arg[0][0] is the same as arg[0], so arg[0] is changed, not the location arg[0] points to.
    printf("\tIn-function ver[0] = %d\n",arg[0][0]);

    free(arg[0]); //This one doesn't work...
    free(arg); //This one works though.
}

答案 3 :(得分:0)

为什么在您的代码中发表此评论?

free(arg[0]); //This one doesn't work...

我认为它确实有效,它将数据var点释放出来,然后你再次释放它。
您的调试数据显示

ver addr 2: 00B8AFF0
Freeing arg[0] = 00B8AFF0

如果你第一次释放它时注释掉它仍然会失败?
你第一次解放它后就用它了:

printf("ver[0] new value: %d\n", ver[0]); /// but you already freed that

尝试使用

void *xmalloc(int s) {
  char *ret = malloc(s);
  printf("malloc(%d)==%p\n", s, ret);
  return ret;
}
void xfree(void *b) {
  printf("free(%p)\n", b);
  free(b)
  return;
}
#define malloc xmalloc
#define free xfree

我在C工作已经很长时间了。
初始化变量。

int** var = NULL;
int* ver = NULL;

在释放数据块之前,请将其设置为全零(或其他值)。

memset(void_ptr, 0, sizeof_your_data);

如果你删除所有那些打印语句,那么读代码会更容易......虽然我知道它们对调试很有用...试试(先备份)。