0

Recently I stumbled upon source code where programmer declared variables inside one infinite loop depending on if/else conditions. What I found odd is that the code ran and it didn't implied any memory leaks. First I thought that maybe it was architecture specific thing (the code was for ARM) but I ran some tests and I found out that binaries on IA32 compiled with GCC acted in same way.

My approach was like this: I've created two small program foo.c and bar.c

Foo.c:

#include <stdio.h>

int main(void)
{
   int i;

   for(i=0; i<10; i++) {
      char buf[10];
      buf[i] = 0;
      printf("buf[%d] (@ %#x) == %d\n", i, &buf, buf[i]);
   }

   return(0);
}

Bar.c:

#include <stdio.h>

int main(void)
{
   int i;

   for(i=0; i<10; i++) {
      char *ptr;
      ptr = (char *) malloc(10);
      ptr[i] = 0;
      printf("buf[%d] (@ %#x) == %d\n", i, &ptr, ptr[i]);
   }

   return(0);
}

The reason behind making explicit distinction between declaring an array in Foo.c and allocating memory in Bar.c was that first I thought that maybe compiler auto-magically detects that it's the same variable and just ignoring the declaration after initial for iteration which of course shouldn't be the case in Bar.c because I explicitly allocate the memory.

What was really weird to me that in both examples the address of both an array and allocated memory stays the same after initial for iteration.

I do not completely understand that and I don't have my copy of K&R with me so I'll be thankful for an explanation. (Also if I made any mistake in my reasoning I'd be glad for pointing it out.)

4

2 回答 2

2

不要打印指针的地址ptr(这是循环内的常量,因为ptr在当前调用帧中是局部变量),而是打印指针本身:

 printf ("buf[%d] == %d, ptr == %p\n", i, ptr[i], (void*) ptr);

(请记住,如果a是一个数组,你确实有&a == a并且它们的类型是兼容的,但是如果p是一个指针,你通常没有&p == p,并且它们的类型是不兼容的)

当然,如果您malloc在循环内有一些指针,您通常希望free该指针位于循环体的末尾。

您应该学习使用gcc -Wall -g(在 Linux 上,甚至可能使用-Wextra)进行编译和使用调试器gdb(在 Linux 上)。

valgrind是 Linux 上捕获内存泄漏的有用工具。您可以使用Boehm 的保守垃圾收集器来“避免”它们(通过使用GC_malloc而不是,而不是为-ing 显式内存malloc而烦恼)。free

于 2012-06-24T15:37:44.513 回答
1
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int i;
    for(i=0; i<10; i++) {
    char *ptr;
    ptr = malloc(10);
    ptr[i] = 0;
    printf("buf[%d] ptr is %#x, &ptr is %#x, ptr[i] is %d\n", i, ptr, &ptr, ptr[i]);
    }
    return 0;
}

我在 bar.c 的输出中添加了 ptr。现在你可以找到答案了。这是新的源代码 bar.c。我修复了其他人提到的所有错误。你可以通过“gcc -o bar bar.c”编译它并运行“./bar”。

输出是:

    ./bar
    buf[0] ptr is 0x820a008, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[1] ptr is 0x820a018, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[2] ptr is 0x820a028, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[3] ptr is 0x820a038, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[4] ptr is 0x820a048, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[5] ptr is 0x820a058, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[6] ptr is 0x820a068, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[7] ptr is 0x820a078, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[8] ptr is 0x820a088, &ptr is 0xbfb9dc48, ptr[i] is 0
    buf[9] ptr is 0x820a098, &ptr is 0xbfb9dc48, ptr[i] is 0

您可以发现 ptr 的值在每一行都发生了变化,但 &ptr 的值保持不变。结论:ptr在每次“for”迭代时分配不同的内存,但ptr的地址并没有改变。

于 2015-01-16T02:27:56.797 回答