【问题标题】:Segmentation fault after freeing completely different memory释放完全不同的内存后出现分段错误
【发布时间】:2011-11-09 08:56:08
【问题描述】:

我有一个蒙特卡罗模拟,它应该运行多次,然后对各个结果进行平均。每次运行后,我想为模拟中需要的东西释放分配的内存。其中一个东西是sites 的数组,其中每个site 是一个结构,它有一个SLE 类型的链表作为一个成员。所以为了全部释放,我先遍历链表,释放每个节点,然后释放sites数组的内存。

SLE * neighbor, * tmp;
int i;
for(i = 0; i < args.nsites_arg; ++i)
{
    // free neighbor memory
    neighbor = sites[i].neighbors;
    while(neighbor)
    {
        tmp = neighbor->next;
        free(neighbor);
        neighbor = tmp;
    }
}
free((void *)sites);

然而,发生了一些非常奇怪的事情:模拟运行良好一次,然后重新开始。我为sites 重新分配了所有需要的内存,并重写了上面提到的SLEs 的链表。然后,在前一个数组的一些排序操作中,它给了 mit 一个段错误:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000408468 in sortNeighbors (list=0xad0e00) at mc_init.c:485
485         while(temp && temp->next)

当我在上面的 sn-p 中删除 free(neighbor) 时,它工作正常。正如我所说,一切都像第一次运行之前一样重新分配。那么这里会发生什么?我如何收集更多关于真正释放什么以及为什么会发生这种段错误的信息?


编辑:另一个奇怪的事情是,这个排序的开头是这样的:

if (!list || !list->next)
    return list;

SLE * temp = list;

// Find halfway through the list
while(temp && temp->next)
{

我明确检查 listlist-&gt;next 是否存在,那么为什么它会在 while 条件下给出段错误?


Edit2:分配

sites = (Site *) malloc(args.nsites_arg * sizeof (Site));
...
// s is now one element of the sites array
while(siteList)
{
    neighbors       = (SLE*) malloc(sizeof (SLE));
    ...
    neighbors->next = s->neighbors;
    s->neighbors    = neighbors;
    siteList = siteList->next;
}

【问题讨论】:

  • 我担心(void *)sites 在您对free(3) 的调用中强制转换——这通常意味着您忘记包含stdlib.h 标头,因此无法访问@ 987654337@原型。
  • 你是如何声明、分配和初始化sites的?
  • 你说你重新分配 sites ,但你是否也将所有未使用的东西设置为 NULL - 或者确保所有旧的东西都消失/擦除,所以你没有在任何地方触摸悬空指针?
  • 你能在 valgrind 之类的东西中运行它吗?希望它能为您提供更多信息。
  • 您是否在禁用优化的情况下进行编译?

标签: c memory-management free


【解决方案1】:

如果您使用的是 linux,请查看我的回答 here。这是关于 valgrind,一个帮助调试段错误、内存泄漏等的工具。

当您通过访问释放的内存(我理解您的情况)获得 SIGSEV 时,它会告诉您内存被释放的位置 - 它没有必要通过您的 sn-p 中的 free 调用释放。

【讨论】:

  • 我稍后会尝试深入研究valigrind。感谢您的链接!
【解决方案2】:

在搜索错误之前,您可能希望使用已经实现且经过良好测试的single or double linked lists

或者,如果您不想担心内存错误,请链接到gc garbage collector(假设您的模拟的实际计算完成了它应该做的事情)

【讨论】:

  • 感谢您的链接。我实际上希望尽可能简单地保持依赖关系,并且由于我仍在学习 C 的过程中,我真的很想找到问题并自己解决。另外,自己进行内存管理会让你更加小心。至于链表:它们由一些大结构组成,所以我想我会保留我的实现。
【解决方案3】:

一些更好的 Windows 商业工具:

  • 净化
  • 保险++

【讨论】:

    【解决方案4】:

    尝试通过 valgrind 运行它:valgind --tool=memcheck [COMMAND]

    开箱即用,没有什么特别需要。

    欲了解更多信息,请访问Valgrind 网站。

    【讨论】:

      猜你喜欢
      • 2016-05-08
      • 2014-04-02
      • 1970-01-01
      • 2019-05-21
      • 2023-03-04
      • 2021-11-25
      • 1970-01-01
      • 2021-08-23
      • 2018-01-10
      相关资源
      最近更新 更多