最近有个人在我的一段代码中指出了一个问题
char* name = malloc(256*sizeof(char));
// more code
free(name);
我曾以为这种设定数组的方式与使用
char name[256];
我认为两种方法都需要使用free()函数,如果我错了,能否有人用浅显易懂的术语解释一下区别?
最近有个人在我的一段代码中指出了一个问题
char* name = malloc(256*sizeof(char));
// more code
free(name);
我曾以为这种设定数组的方式与使用
char name[256];
我认为两种方法都需要使用free()函数,如果我错了,能否有人用浅显易懂的术语解释一下区别?
char *foo = malloc(sizeof(*foo))
,以使其更不可能。 - rpetrichvoid doit() {
/* ... */
/* SP += 10 * sizeof(int) */
int a[10];
/* ... (using a) */
} /* SP -= 10 */
void doit(int n) {
int a[n]; // allocate n * sizeof(int) size on the stack */
}
// file foo.c
char name[256];
int foo() {
// do something here.
}
在另一个SO问题的答案中,有人认为这在C语言中是不合适的,这让我感到相当惊讶;但在这里,它甚至没有被提及,我有点困惑和惊讶(就像“他们现在在学校教什么?”)。
如果您使用此定义,则内存是静态分配的,既不在堆上也不在栈上,而是在映像的数据空间中。因此,既不必像使用malloc/free一样进行管理,也不必担心地址会像自动定义一样被重用。
在这里,回想整个“声明”与“定义”的事情是有用的。以下是一个例子:
/* example.c */
char buf1[256] ; /* declared extern, defined in data space */
static char buf2[256] ; /* declared static, defined in data space */
char * buf3 ; /* declared extern, defined one ptr in data space */
int example(int c) { /* c declared here, defined on stack */
char buf4[256] ; /* declared here, defined on stack */
char * buf5 = malloc(256)] /* pointer declared here, defined on stack */
/* and buf4 is address of 256 bytes alloc'd on heap */
buf3 = malloc(256); /* now buf3 contains address of 256 more bytes on heap */
return 0; /* stack unwound; buf4 and buf5 lost. */
/* NOTICE buf4 memory on heap still allocated */
/* so this leaks 256 bytes of memory */
}
现在在一个完全不同的文件中
/* example2.c */
extern char buf1[]; /* gets the SAME chunk of memory as from example.c */
static char buf2[256]; /* DIFFERENT 256 char buffer than example.c */
extern char * buf3 ; /* Same pointer as from example.c */
void undoes() {
free(buf3); /* this will work as long as example() called first */
return ;
}
这是错误的 - 数组声明不需要释放。此外,如果这在一个函数内部,它会在堆栈上分配(如果我的记忆没有出错),并且在函数返回时会自动释放 - 不要将其引用传回调用者!
分解你的语句
char* name = malloc(256*sizeof(char)); // one statement
char *name; // Step 1 declare pointer to character
name = malloc(256*sizeof(char)); // assign address to pointer of memory from heap
name[2]; // access 3rd item in array
*(name+2); // access 3rd item in array
name++; // move name to item 1
翻译:name现在是一个指向字符的指针,它被赋予了堆上某些内存的地址。
char name[256]; // declare an array on the stack
name++; // error name is a constant pointer
*(name+2); // access 3rd item in array
name[2]; // access 3rd item in array
char *p = name;
p[2]; // access 3rd item in array
*(p+2); // access 3rd item in array
p++; // move p to item 1
p[0]; // item 1 in array
翻译:Name是一个指向堆栈上某个内存的字符常量指针。
C语言中,数组和指针本质上是相同的。数组是指向内存的常量指针。主要区别在于当您调用malloc时,会从堆中获取内存,而从堆中获取的任何内存必须从堆中释放。当您使用大小声明数组时,它会被分配在堆栈上的内存中。您无法释放此内存,因为free是用来释放从堆中获取的内存。在当前程序单元返回时,堆栈上的内存将自动释放。在第二个示例中,也不能释放p。p是指向堆栈上name数组的指针。因此,如果释放p,则会尝试释放堆栈上的内存。
这与以下情况没有区别:
int n = 10;
int *p = &n;
在这种情况下释放p将会是一个错误,因为p指向堆栈上的变量n。因此,p保存了堆栈中的内存位置,不能被释放。
int *p = (int *) malloc(sizeof(int));
*p = 10;
free(p);
根据您运行代码的位置,堆栈空间可能非常宝贵。例如,如果您正在为Verizon/Alltel手机编写BREW代码,则通常受到微小堆栈的限制,但具有越来越多的堆访问权限。
此外,由于char[]最常用于字符串,因此允许字符串构造方法为所需的字符串分配内存而不是希望永远只需要256(或您指定的任何数字)并不是一个坏主意。