通常来说,我们常常会这样来释放指针所指向的内存:
譬如定义一个结构体:
typedef struct Book {
unsigned char *name;
unsigned char *press;
float price;
}T_Book, *PT_Book;
static T_Book tBook;
若要想释放tBook成员变量name所指向的内存,比较把稳的做法是这样:
if (tBook.name != NULL) {
free(tBook.name);
}
但这样就万无一失吗?下面举一个例子来看一下:
typedef struct Book {
unsigned char *name;
unsigned char *press;
float price;
}T_Book, *PT_Book;
static T_Book tBook;
int main(void)
{
if (tBook.name != NULL)
printf("tBook.name = %d\n", (int)tBook.name);
tBook.press = NULL;
if (tBook.press != NULL)
printf("tBook.press = %d\n", (int)tBook.press);
if (tBook.name != NULL) {
free(tBook.name);
}
return 0;
}
编译、执行,打印信息如下:
tBook.name = 14737600
*** glibc detected *** ./main: munmap_chunk(): invalid pointer: 0x00e0e0c0 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x561591]
/lib/tls/i686/cmov/libc.so.6(+0x6c80e)[0x56280e]
./main[0x8048477]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x50cbd6]
./main[0x8048381]
有错误,错误在哪里呢?
错误在于“定义一个结构体变量,变量内部的指针成员变量编辑器并不会把它默认设置为NULL,它很可能会有一个随机值,而那个值往往没有意义”,所以,当执行到free的if语句时,tBook.name != NULL判断为真,所以free语句得以执行,但tBook.name指针指向的是无效指针,所以会在执行时报错,除了这样的错误之外,笔者还遇到如下错误:
*** glibc detected *** free(): invalid pointer: 0x00016c90 ***
Aborted
如何避免这样的错误?初始化指针为NULL就好了!
再回过头来看上面的free函数,这样的方式有问题吗?
当然!
if (tBook.name != NULL) {
free(tBook.name);
}
free(tBook.name)的结果只会让系统把tBook.name所指向的内存给清空了,但是此函数的结果并不会改变tBook.name的值,换句话说,需要手动在free之后设置tBook.name的值为NULL,即:
if (tBook.name != NULL) {
free(tBook.name);
tBook.name = NULL;
}
这才是更稳妥的做法。