【问题标题】:free() on stack memory堆栈内存上的 free()
【发布时间】:2011-02-11 05:27:28
【问题描述】:

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

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

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

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

【问题讨论】:

  • 这是谁写的?那家伙应该是free()'d。
  • 这是一个错误,但 free 可能知道堆的边界并且可以发现这一点。这个项目也有可能有一个堆分配库,它进行垃圾收集和 free 要么什么都不做,要么是一个宏,如 #define free(x) (x=NULL)
  • @nategoose:如果是这样,那不是那个宏,因为new_login = 0 不应该编译。

标签: c memory-management garbage-collection stack free


【解决方案1】:

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

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

【讨论】:

  • “考虑这是一个严重的错误,并尽快删除该行”。这是一个非常严重的错误,如果当前代码运行正确,我想在更改它之前尝试找出原因。可能有一些我严重误解的东西(比如其中一个令牌实际上是new_1ogin 或其他东西)。我可能会浪费我的时间,但我会那么偏执;-)
  • 也许,free 检查指针的范围,当它来自堆外的区域时什么也不做。恕我直言,这不是一个好主意,但谁知道实施者的想法(在我以前的嵌入式程序员生活中,我什至在我们的一个采集控制器上实现了这种行为)。
  • 同意,但在特定的实现中,“也许”变成“要么有,要么没有”。我一直想知道哪些错误在实践中可以检测到,哪些不能检测,因为这样可以更轻松地智能调试未来的问题。
  • 如果您打算将该测试放入您的 free() 实现中,您可能会做更多的事情来处理它而不是“默默地忽略”。
  • 这可能不是错误。 Malloc 钩子本质上可以定义不同于标准中定义的行为。
【解决方案2】:

没有。这是一个错误。

根据free(3)....

free() 释放指向的内存空间 到 ptr,这一定是 由先前调用返回 malloc()、calloc() 或 realloc()。 否则,或者如果 free(ptr) 已经 之前被调用过,未定义 行为发生。如果 ptr 为 NULL,则否 执行操作。

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

【讨论】:

    【解决方案3】:

    在大多数情况下,您只能 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);
    }
    ...
    

    【讨论】:

      【解决方案4】:

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

      
         strcpy(new_login, (char *)login);
      

      如果该函数没有迂腐地确认登录是 63 个或更少的字符并具有适当的 null 终止,那么此代码具有典型的缓冲区溢出错误。如果恶意方可以用正确的字节填充登录,他们可以覆盖堆栈上的返回指针并执行任意代码。一种解决方案是:
      
         new_login[sizeof(new_login)-1]='\0';
         strncpy(new_login, (char *)login, sizeof(new_login)-1 );
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 2011-08-01
          • 2019-03-27
          • 1970-01-01
          • 2012-04-12
          • 2014-10-13
          • 2011-08-15
          • 2017-02-08
          • 2012-06-03
          • 2018-09-17
          相关资源
          最近更新 更多