C 循环内的变量和分配
最近我偶然发现了源代码,其中程序员根据if/else条件在一个无限循环中声明变量。我发现奇怪的是,代码运行时并没有暗示任何内存泄漏。首先,我认为这可能是特定于体系结构的东西(代码是针对ARM的),但我运行了一些测试,发现使用GCC编译的IA32上的二进制文件也以同样的方式运行 我的方法是这样的:我创建了两个小程序foo.c和bar.c Foo.c:C 循环内的变量和分配,c,memory-management,compiler-construction,memory-leaks,C,Memory Management,Compiler Construction,Memory Leaks,最近我偶然发现了源代码,其中程序员根据if/else条件在一个无限循环中声明变量。我发现奇怪的是,代码运行时并没有暗示任何内存泄漏。首先,我认为这可能是特定于体系结构的东西(代码是针对ARM的),但我运行了一些测试,发现使用GCC编译的IA32上的二进制文件也以同样的方式运行 我的方法是这样的:我创建了两个小程序foo.c和bar.c Foo.c: #include <stdio.h> int main(void) { int i; for(i=0; i<10;
#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);
}
#包括
内部主(空)
{
int i;
对于(i=0;i不打印指针的地址ptr
(这是循环中的一个常量,因为ptr
在当前调用帧中是一个局部变量),而是打印指针本身:
printf ("buf[%d] == %d, ptr == %p\n", i, ptr[i], (void*) ptr);
(请记住,如果a
是一个数组,您确实有&a==a
并且它们的类型是兼容的,但是如果p
是指针,您通常没有&p==p
,并且它们的类型是不兼容的)
当然,如果您malloc
循环中的某个指针,通常希望释放循环体末端的该指针
您应该学习使用gcc-Wall-g
(在Linux上,甚至可能还使用-Wextra
)进行编译,并使用调试器gdb
(在Linux上)
是Linux上用于捕获内存泄漏的有用工具。您可以使用它来“避免”内存泄漏(使用GC\u malloc
而不是malloc
,并且不必为free
-ing显式占用内存而烦恼)。不要打印指针的地址ptr
(这是循环中的一个常量,因为在当前调用帧中,ptr
是一个局部变量),但打印指针本身:
printf ("buf[%d] == %d, ptr == %p\n", i, ptr[i], (void*) ptr);
(请记住,如果a
是一个数组,您确实有&a==a
并且它们的类型是兼容的,但是如果p
是指针,您通常没有&p==p
,并且它们的类型是不兼容的)
当然,如果您malloc
循环中的某个指针,通常希望释放循环体末端的该指针
您应该学习使用gcc-Wall-g
(在Linux上,甚至可能还使用-Wextra
)进行编译,并使用调试器gdb
(在Linux上)
是Linux上用于捕获内存泄漏的有用工具。您可以使用它来“避免”内存泄漏(使用GC\u malloc
而不是malloc
,并且不必为释放内存而烦恼)
您可以发现ptr的值在每一行都会发生变化,但&ptr的值保持不变。
结论:ptr在每次“for”迭代时分配不同的内存,但ptr的地址不变
您可以发现ptr的值在每一行都会发生变化,但&ptr的值保持不变。
结论:ptr在每个“for”分配不同的内存迭代,但是PTR的地址没有改变。< /P> C++是不同于C的语言,你不知道吗?和<代码>返回<代码>不是一个函数…@安迪,请用英文写。如果他们想回答C问题,他们会订阅C标签。用不合适的标签来更多地关注你的问题被认为是粗鲁的。安迪:不。C和C++。是不同的语言。你不应该抛出MalCube()的返回值,你应该<代码> >包含C中的< /Cord> @安迪,你不必抛出,这是坏的风格。在C++中,你必须(但是无论如何都不应该使用<代码> MaloC < /COD>)不同的语言。非常不同。C++是不同于C的语言,你不知道吗?和<代码>返回<代码>不是一个函数…@安迪,请用英语写。如果他们想回答C问题,他们会订阅C标签。用不合适的标签来更多地关注你的问题被认为是粗鲁的。安迪:不,C和C++是不同的LA。你不应该投MalCube()的返回值,你应该<代码> >包含C中的< /Cord> @安迪,你不需要抛出,这是坏的风格。在C++中,你必须(但是无论如何都不应该使用<代码> MaloC < /COD>)。不同的语言。非常不同。老实说,它应该是gcc-Wall-Wextra
,因为-Wall
实际上是-wnotall
(有时使用-Werror
很方便).不管我是做&ptr还是ptr,这都无关紧要,因为这与我问的问题无关。为什么?因为即使我打印出ptr而不是&ptr,我仍然得到了相同的基址。我在问为什么每次迭代中用malloc显式分配内存时都是一样的。在这个例子中,释放也是毫无意义的(因为我想造成内存泄漏)。@Griwes-Wall
包含了最常用的警告,但是,-Wextra
启用的很多警告都是主观的,或者试图猜测最佳做法。@andy,编码ptr
与&ptr
不同,所以你说错了:“不管我是执行&ptr
还是ptr
”@delnan-Wextra
的示例(从手册页):缺少返回
语句(或多或少都是错误)、有符号/无符号比较(不一定是错误,但可以隐藏糟糕的错误)、缺少字段初始化器(几乎总是错误)。老实说,它应该是gcc-Wall-Wextra
,因为-Wall
实际上是-wnotall
(有时使用-Werror
很方便).不管我是做&ptr还是ptr,这都无关紧要,因为这与我问的问题无关。为什么?因为即使我打印出ptr而不是&ptr,我仍然得到了相同的基址。我在问为什么每次迭代中用malloc显式分配内存时都是一样的。在这个例子中,释放也是毫无意义的(因为我想造成内存泄漏)。@Griwes-Wall
包含了最常用的警告,但是-Wextra
启用的很多警告都是主观的,或者试图猜测最佳做法。@andy,coding
#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
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