9

我在 Solaris 上支持一些 c 代码,我看到了一些奇怪的东西,至少我认为是:

char new_login[64];
...
strcpy(new_login, (char *)login);
...
free(new_login);

我的理解是,由于变量是本地数组,内存来自堆栈,不需要释放,而且由于没有使用 malloc/calloc/realloc,所以行为是未定义的。

这是一个实时系统,所以我认为这是在浪费周期。我错过了一些明显的东西吗?

4

5 回答 5

19

您只能 free() 从 malloc()、calloc() 或 realloc() 函数中获得的东西。释放堆栈上的东西会产生未定义的行为,你很幸运这不会导致你的程序崩溃,或者更糟。

考虑这是一个严重的错误,并尽快删除该行。

于 2010-04-22T19:07:32.593 回答
7

不,这是一个错误。

根据免费(3)....

free() 释放 ptr 指向的内存空间,该内存空间必须由先前对 malloc()、calloc() 或 realloc() 的调用返回。否则,或者如果之前已经调用过 free(ptr),则会发生未定义的行为。如果 ptr 为 NULL,则不执行任何操作。

因此,您的程序中发生了未定义的行为。

于 2010-04-22T19:06:48.847 回答
4

在大多数情况下,您只能 free() 在堆上分配的东西。请参阅http://www.opengroup.org/onlinepubs/009695399/functions/free.html

但是:做你想做的事情的一种方法是限定在堆栈上分配的临时变量的范围。像这样:

{
char new_login[64];
... /* No later-used variables should be allocated on the stack here */
strcpy(new_login, (char *)login);
}
...
于 2010-04-22T20:54:19.727 回答
4

free() 绝对是一个错误。
但是,这里可能还有另一个错误:


   strcpy(new_login, (char *)login);

如果该函数没有迂腐地确认登录是 63 个或更少的字符并具有适当的空终止,那么此代码具有典型的缓冲区溢出错误。如果恶意方可以用正确的字节填充登录名,他们就可以覆盖堆栈上的返回指针并执行任意代码。一种解决方案是:


   new_login[sizeof(new_login)-1]='\0';
   strncpy(new_login, (char *)login, sizeof(new_login)-1 );
于 2010-04-22T22:38:14.433 回答
3

绝对是一个错误。free()只能用于堆分配的内存,除非它被重新定义为完全不同的事情,我怀疑是这种情况。

于 2010-04-22T19:08:09.833 回答