快速问题
在不先调用malloc的情况下,是否可以使用free()函数?
例如。
void someFunc( void )
{
char str[6] = {"Hello"};
//some processing here ....
free(str);
}
我没有遇到编译错误,但这个代码是否能够正确工作?非常感谢。
这完全不正确:
char str[6]
。str
将在堆栈上分配,并且在函数返回时将自动释放。是的,使用0或NULL或空指针调用free()并不是问题。 - Zabba在未malloc的变量上使用free通常会导致段错误。例如:
#include <stdlib.h>
int main()
{
char str[6] = {"Hello"};
free(str);
}
$ gcc test.c -o test
$ ./test
分段错误
free()使用在分配块之前的数据来管理堆。如果指向的内存不是通过像malloc()或calloc()这样的堆分配函数分配的,则块之前的数据将作为堆管理数据毫无意义。
一些库会检测无效的堆数据并产生运行时错误,否则行为是未定义的。通常这种错误的后果只有在稍后尝试分配更多内存时才会被注意到。这使得调试此类错误非常困难。
您不会得到编译器错误,因为它不是语法错误,也不可在编译时检测到。编译器不知道库函数的语义。它所知道的只是malloc()返回一个void*,free()接受一个void*;在编译时没有办法知道指针是否指向动态分配的块,因为内存按定义是在运行时分配的。此外,指针可以在运行时修改以指向任何类型的内存,或者可以别名-复制到另一个指针,然后通过第二个指针进行释放。如果您期望编译器提供错误消息,那么您对编译器的期望很高;但是某些静态分析工具可能能够警告此类错误可能发生,而动态分析工具(如valgrind)可能会在测试期间检测到错误。
{}
引入作用域,像这样:void someFunc( void )
{
// do some stiff here ...
{ // <- introduce a temporary scope
char str[6] = {"Hello"}; // this is local to your new scope
// some processing here ...
} // <- your array str[] is destroyed here
// do some more stuff here, str[] has disappeared
}
为了清晰起见,没有额外的注释:
void someFunc( void )
{
// do some stiff here ...
{
char str[6] = {"Hello"};
// some processing here ...
}
// do some more stuff here ...
}
在函数内部引入新的作用域是一种常见的习惯用法,它可以清理掉广泛作用域中的多余变量(可能是 bug 的潜在来源),同时也可以利用 RAII 的强大功能。
例如,在同步函数代码的一小部分时锁定 mutex。
free(3)
函数接受一个void *
参数,因此您可以传递任何类型的指针而不会出现编译时错误。但是,如果指针最初不是由malloc(3)
返回并且以前从未返回给free(3)
,则会发生糟糕的事情。
malloc
的情况下使用free
,但前提是您传递给free
的值必须是空指针。因此,如果您想要一个指针,它可能指向已分配的块,但可能指向本地数组,则无法使用。 - Steve Jessop