为什么这个程序没有崩溃,是不是未定义的行为?
int main()
{
char* c;
if (c) {
printf("called free\n");
free (c);
}
else {
printf("not called free\n");
}
printf("not crashed\n");
c = strdup("someString");
if (c) {
printf("called free\n");
free(c);
c = NULL; // why is this needed for last if (c)
}
if (c) {
free(c);
}
printf("still not crashed\n");
return 0;
}
这个程序有没有可能崩溃?
行为,使用不可移植或错误的程序构造或 错误数据,为此国际标准强加没有 要求。¹
任何事情都可能发生,包括崩溃。
我是否应该在拨打 free 之前总是进行这样的 if (c) 验证 字符* ?
不,使用
free()
指针常量调用 NULL
是 NOP,即不执行任何操作。所以没必要。
如果 ptr 是空指针,则不会发生任何操作。²
为什么没有 c=NULL free 被称为?
因为
free()
函数没有将原始指针设置为NULL
。 c
仍然指向相同的内存位置,但 c
无法再访问它。
free函数使得ptr指向的空间为 释放,即可用于进一步分配。³
如果不将
c
设置为 NULL
,对 free()
的后续调用将释放已经释放的内存,这也会调用未定义的行为。
否则,如果参数与先前返回的指针不匹配 通过内存管理功能,或者如果空间已被释放 通过调用 free 或 realloc,行为未定义。⁴
[1] - [2] - [3] - [4] - C11 标准,7.22.3.3
free
函数。
这段代码片段
char* c;
if (c) {
printf("called free\n");
free (c);
}
else {
printf("not called free\n");
}
调用未定义的行为,因为指针
c
未初始化。
至于这段代码片段
if (c) {
printf("called free\n");
free(c);
c = NULL; // why is this needed for last if (c)
}
if (c) {
free(c);
}
那么如果指针
c
不会被设置为NULL
c = NULL; // why is this needed for last if (c)
然后在下一个 if 语句中,将尝试释放已释放的内存,再次调用未定义的行为。
未定义的行为不一定会使程序崩溃。例如,在第一个代码片段中,指针
c
可以在内部设置为 NULL
.
注意你可以为空指针调用函数
free
。在这种情况下,不会发生任何操作。
指针值分为三种:
&
,或通过调用 malloc
或 realloc
或 strdup
,只要指针没有变得无效。&
)指向不再活动的函数(“堆栈框架”)中的局部变量的指针;曾经使用 malloc
或其他分配的指针,但后来使用 free
释放,或使用 realloc
重新分配。您可以使用普通比较判断指针是否属于类别 1:
if(p == NULL)
,if(p != NULL)
.
但关键是没有编程方式来区分类别 2 和 3 中的指针值。也就是没有办法写
if(valid(p))
或者if(invalid(p))
。
因此,当您知道指针变量无效时,将指针变量设置为 NULL 是一个好习惯。