C -释放数组中的指针

时间:2022-09-30 21:17:50

I've been trying to have all my pointers that I use malloc to initialize to be inside an array of pointers (or a pointer of pointers, perhaps), so that I can then just go through that array and free each pointer with something like free(ptr_array[i]); and not have to free each one individually.

我一直在试着让我用malloc初始化的所有指针都在一个指针数组(或者一个指针,也许)中,这样我就可以遍历这个数组并释放每个指针,比如free(ptr_array[I]);而不需要每个人单独释放。

I believe that this is possible, but I am having some trouble with my code, as the function that is supposed to free everything (and I would rather keep it all in a separate function, if possible) is apparently unable to properly edit the "sub-pointers", and seemingly they're being copied unlike the "main pointer".

我相信这是可能的,但我有一些麻烦,我的代码,功能,应该是免费的一切(我宁愿保持它在一个单独的函数,如果可能的话)显然是无法正确编辑“sub-pointers”,似乎他们被复制与“主要指针”。

Here's the code, which has me stumped:

这是密码,让我困惑:

#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;
}

And this is the output it currently gives me:

这是它现在给我的输出:

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. :(

I'm not too great with C, and thus any help would be appreciated. Specially since the value of ver[0] is altered inside the function, but not outside, and I'm guessing that will have to do with why free(...) doesn't work too.

我对C不是很在行,所以我很感激你的帮助。特别是由于ver[0]的值是在函数内部修改的,而不是在函数外部修改的,我猜这与free(…)为什么不能工作有关。

Thanks in advance.

提前谢谢。

4 个解决方案

#1


1  

Well my knowledge of C is fading, but IIRC subsequent memory freeing causes undefined behaviour. Thus you are not guaranteed to recive any errors. If I understand it right the behaviour will be varying heavily depending on a particular OS, compiler and stdlib implementation (and even a particular program run).

我对C的认识正在衰退,但是IIRC的后续记忆释放导致了不确定的行为。因此,您不能保证收到任何错误。如果我正确地理解了它,那么行为将根据特定的操作系统、编译器和stdlib实现(甚至是特定的程序运行)而变化很大。

P.S. My VS2012 VC++ compiler definetly breaks on free(ver);. The output is:

我的VS2012 VS2012 vvvc++编译器肯定会在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.

#2


1  

I have tested your code on gcc 4.6.3 and find that this program does not have any memory leaks using valgrind. And when I delete the line "free(ver)" in main, the program runs perfectly and does not have any memory leak either. I think free_test routine has successfully freed those two malloc you have in main. As for why there is not any coredump pops out when freeing the var again in the program, it depends on different OS implementation.

我已经在gcc 4.6.3上测试了您的代码,发现这个程序没有任何使用valgrind的内存泄漏。当我删除主行“free(ver)”时,程序运行良好,也没有任何内存泄漏。我认为free_test例程已经成功地释放了您主要拥有的两个malloc。至于为什么在程序中再次释放var时不会弹出任何coredump,这取决于不同的OS实现。

Test it with valgrind and you will find it useful if you want to check memory leaks involving malloc and free.

使用valgrind进行测试,如果您想检查包含malloc和free的内存泄漏,您会发现它非常有用。

#3


0  

Use

使用

"* (*(arg+0)+0)"

“*(*(arg + 0)+ 0)”

instead of [][]. Syntax like [][]...[] only dereference pointer once. Each [] only change the semantic of pointer (how many location it jumps when +1), have nothing to do with dereference times.

而不是[][]。语法就像[][]…只删除一次引用指针。每个[]只改变指针的语义(当+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.
}

#4


0  

Why this comment in your code?

为什么要在代码中添加这个注释?

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

I think it did work, and it freed the data var points to, and then you freed it again.
Your debug data shows

我认为它确实有效,它释放了数据var点,然后你又释放了它。调试数据显示

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

If you comment out the first time you freed it, it still fails?
and you used it after freeing it the first time:

如果你第一次释放它,它还是失败了?第一次释放后你用了它

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

Try using

试着用

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

It's been a long time since I worked in C.
Initialize your variables.

我在c工作已经有很长时间了,初始化你的变量。

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

Before you free a block of data, set it to all zeros (or some other value).

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

memset(void_ptr, 0, sizeof_your_data);

It's a LOT easier to read your code if you delete all those print statements... though I know they are useful for debugging... try it (make a backup first).

如果你删除了所有的打印语句,阅读你的代码要容易得多。虽然我知道它们对调试很有用……试试(先做个备份)。

#1


1  

Well my knowledge of C is fading, but IIRC subsequent memory freeing causes undefined behaviour. Thus you are not guaranteed to recive any errors. If I understand it right the behaviour will be varying heavily depending on a particular OS, compiler and stdlib implementation (and even a particular program run).

我对C的认识正在衰退,但是IIRC的后续记忆释放导致了不确定的行为。因此,您不能保证收到任何错误。如果我正确地理解了它,那么行为将根据特定的操作系统、编译器和stdlib实现(甚至是特定的程序运行)而变化很大。

P.S. My VS2012 VC++ compiler definetly breaks on free(ver);. The output is:

我的VS2012 VS2012 vvvc++编译器肯定会在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.

#2


1  

I have tested your code on gcc 4.6.3 and find that this program does not have any memory leaks using valgrind. And when I delete the line "free(ver)" in main, the program runs perfectly and does not have any memory leak either. I think free_test routine has successfully freed those two malloc you have in main. As for why there is not any coredump pops out when freeing the var again in the program, it depends on different OS implementation.

我已经在gcc 4.6.3上测试了您的代码,发现这个程序没有任何使用valgrind的内存泄漏。当我删除主行“free(ver)”时,程序运行良好,也没有任何内存泄漏。我认为free_test例程已经成功地释放了您主要拥有的两个malloc。至于为什么在程序中再次释放var时不会弹出任何coredump,这取决于不同的OS实现。

Test it with valgrind and you will find it useful if you want to check memory leaks involving malloc and free.

使用valgrind进行测试,如果您想检查包含malloc和free的内存泄漏,您会发现它非常有用。

#3


0  

Use

使用

"* (*(arg+0)+0)"

“*(*(arg + 0)+ 0)”

instead of [][]. Syntax like [][]...[] only dereference pointer once. Each [] only change the semantic of pointer (how many location it jumps when +1), have nothing to do with dereference times.

而不是[][]。语法就像[][]…只删除一次引用指针。每个[]只改变指针的语义(当+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.
}

#4


0  

Why this comment in your code?

为什么要在代码中添加这个注释?

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

I think it did work, and it freed the data var points to, and then you freed it again.
Your debug data shows

我认为它确实有效,它释放了数据var点,然后你又释放了它。调试数据显示

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

If you comment out the first time you freed it, it still fails?
and you used it after freeing it the first time:

如果你第一次释放它,它还是失败了?第一次释放后你用了它

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

Try using

试着用

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

It's been a long time since I worked in C.
Initialize your variables.

我在c工作已经有很长时间了,初始化你的变量。

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

Before you free a block of data, set it to all zeros (or some other value).

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

memset(void_ptr, 0, sizeof_your_data);

It's a LOT easier to read your code if you delete all those print statements... though I know they are useful for debugging... try it (make a backup first).

如果你删除了所有的打印语句,阅读你的代码要容易得多。虽然我知道它们对调试很有用……试试(先做个备份)。