【问题标题】:Can you determine if a string if freeable in C? [duplicate]你能确定一个字符串是否可以在 C 中释放吗? [复制]
【发布时间】:2011-09-20 19:13:45
【问题描述】:

如果我说:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *x;
char *y;

int main() {
        x = malloc(sizeof("Hello, world!"));
        strcpy(x, "Hello world!");
        y = "Hello, world";
        free(x);
        fprintf(stderr, "okay");
        free(y);
}

然后,很明显,程序将打印“okay”,然后因为“未分配被释放的指针”而死亡——显然,因为字符串是字符串文字。

我想编写一个函数,它在给定字符串文字时不执行任何操作,但在给定非字符串文字时调用 free。这可能吗?如果可以,怎么做?

【问题讨论】:

  • Nope :) 这就是内存管理的乐趣所在——开发人员负责跟踪这些有趣的事情。
  • @DeadMG,我相信这同样适用于 C 和 C++。
  • 不要在文字上免费调用。这是最简单的解决方案。
  • @mark 文字是在堆上还是栈上?如果两者都不是,那么这如何与另一个问题重复。其他问题。
  • @David:实现这一目标的简单方法是遵循更一般的建议:始终将字符串文字的地址分配给const char *,而不是char *

标签: c malloc


【解决方案1】:

我认为该标准没有任何东西可以检查指针是否由 malloc 返回(你只应该将它们传递给 free)所以我会说不,你找不到那个.您必须自己跟踪它。

【讨论】:

  • +1:这是迄今为止唯一没有暗示某些可怕的不可移植、非稳健机制的答案,而是简单地说“不要那样做”。
  • @Oli:是的,但 OP 并没有说他需要便携式解决方案。
【解决方案2】:

没有。在 C 中,您必须跟踪自己分配的内容。

一些malloc 实现(例如dlmalloc)提供了一些额外的功能来检查堆,但你不应该依赖这些。 dlmalloc 具有函数dlmalloc_inspect_all,它将遍历堆并将malloc 分配的所有内存区域返回给您,内存映射块除外。所以你可以用它来测试一个指针是否指向一个非内存映射的分配,但总的来说这仍然是一个坏主意。

在 Windows 上,甚至不要考虑使用 [IsBadReadPtr] 来测试指针是否指向可读内存 -- it should really be called CrashProgramRandomly

【讨论】:

    【解决方案3】:

    没有便携的方式。但是,由于大多数实现将堆对象分配在与文字(字符串)数据不同的内存区域中,因此如果给定的字符串指针落在任一区域内,就有可能做出有根据的猜测。

    static char    x;
    
    bool isStatic(const void *p)
    {
        const char *  cp = (const char *)p;
    
        // Check if the pointer falls within +/-16K of 'x'
        if (cp-16*1024 <= &x  &&  &x <= cp+16*1024)
            return true;
        else
            return false;
    }
    

    很明显,这有点小题大做。更好的方法是在加载到内存后直接访问可执行文件的.bss.data.text 地址(这些是Unix,Win32 类似),并比较指向这些区域的指针。

    【讨论】:

      【解决方案4】:

      如果您在执行时对程序的内存映射有所了解,那么您也许可以做一些事情。不过,更好的办法是进行适当的内存管理。

      【讨论】:

        【解决方案5】:

        您可以为 malloc 编写一个包装器,用于跟踪已分配内存的地址。然后在您的免费功能中,您可以查看该内存是否在列表中。

        除此之外,您也许可以使用堆,但它甚至不能远程移植。

        但为什么不构建某种类型的 GC 或使用 GC 库。

        【讨论】:

          猜你喜欢
          • 2011-03-26
          • 2010-11-17
          • 2012-11-30
          • 2011-08-07
          • 1970-01-01
          • 2014-02-09
          • 2015-03-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多