【问题标题】:Map causing Seg Fault. How to increase memory?导致 Seg 故障的映射。如何增加记忆力?
【发布时间】:2011-09-29 21:53:25
【问题描述】:

我有一个简单的问题。我有几个文件,一个文件大约 20000 行。
它有 5 个字段,还有一些其他的 adt(向量和列表),但这些不会导致段错误。 地图本身将存储一个键值,相当于每行大约 1 个。 当我在我的代码中添加地图时,我会立即得到一个段错误,我复制了 20000 行中的 5000 行,然后收到一个段错误,然后是 1000 行,并且它起作用了。

在 java 中有一种方法可以增加虚拟分配的内存量,有没有在 c++ 中这样做的方法?我什至删除了不再使用的元素,我可以得到大约 2000 行,但不会更多。

这里是 gdb:

(gdb) exec-file readin
(gdb) run
Starting program: /x/x/x/readin readin

Program exited normally.

valgrind:

HEAP SUMMARY:
==7948==     in use at exit: 0 bytes in 0 blocks
==7948==   total heap usage: 20,206 allocs, 20,206 frees, 2,661,509 bytes allocated
==7948== 
==7948== All heap blocks were freed -- no leaks are possible

代码:

 ....
 Flow flw = endQueue.top();
  stringstream str1;
  stringstream str2;
  if (flw.getSrc() < flw.getDest()){
    str1 << flw.getSrc();
    str2 << flw.getDest();
    flw_src_dest = str1.str() + "-" + str2.str();
  } else {
    str1 << flw.getSrc();
    str2 << flw.getDest();
    flw_src_dest = str2.str() + "-" + str1.str();
  }    
while (int_start > flw.getEnd()){
  if(flw.getFlow() == 1){
    ava_bw[flw_src_dest] += 5.5;
  } else {
    ava_bw[flw_src_dest] += 2.5;
  }
  endQueue.pop();
} 

【问题讨论】:

  • 发布您的代码。它在某个地方坏了......
  • 您确定分段错误是由于内存分配问题造成的吗?您是否在 GDB 中运行过代码?在 1,000 个条目后,地图似乎不太可能失败。
  • 如果您在现代虚拟内存环境中执行此操作,问题在于处理映射的代码,而不是内存不足。在 Linux 中,会出现内存限制的资源错误,而不是 SEGFAULT。
  • 我没用过调试的,让我试试,我会回复大家的。
  • std::map 还是您推出了自己的地图类?由于任何标准 C++ 容器,您都不太可能看到分段错误。我们需要看一些代码...

标签: c++ memory memory-management map segmentation-fault


【解决方案1】:

分段错误不一定表示您的内存不足。事实上,对于 C++,不太可能:在这种情况下,您通常会得到 bad_alloc 或类似的东西(除非您将所有内容转储到具有自动存储持续时间的对象中?!)。

更可能的是,您的代码中存在内存损坏错误,恰巧只有当您拥有超过一定数量的对象时才会注意到。

无论如何,内存故障的解决方案不是盲目地向程序投入更多的内存。

通过 valgrind 和调试器运行您的代码,看看真正的问题是什么。

【讨论】:

  • 我跑过调试器,但没有发现任何问题。
  • @Jim: valgrind 会发现这个问题。请安装它以供将来继续使用,作为正常开发环境的一部分,不要因为你的直接错误已经解决而忽略我的建议。
  • 会的,我运行大部分代码的服务器没有它。但是我找到了一个可以让我的电脑运行它的版本。
  • @Jim:理所当然,您应该将 valgrind 放入您的开发环境中。它适用于 Linux。您在什么操作系统上开发?
  • mac 操作系统。我必须使用端口。我正在努力让它发挥作用。
【解决方案2】:

在迭代容器时小心擦除容器中的元素。

for (pos = ava_bw.begin(); pos != ava_bw.end(); ++pos) {
    if (pos->second == INIT){
      ava_bw.erase(pos);
    }
  }

我相信这将使pos 指向下一个值,但随后++pos 将再次推进它。如果erase(pos) 导致pos 指向ava_bw.end(),则++pos 将失败。

我知道如果您尝试使用矢量,pos 将失效。

编辑

在你做的while循环中

while (int_start > flw.getEnd()){
   if(flw.getFlow() == 1){
      ava_bw[flw_src_dest] += 5.5;
   } else {
      ava_bw[flw_src_dest] += 2.5;
   }
   endQueue.pop();
}

你需要再次flw = endQueue.top()

【讨论】:

  • 它做了它应该做的事情?我的意思是我把它注释掉了,我仍然会得到一个段错误。
  • 抱歉所有的编辑。 erase() 具有不同的副作用,具体取决于它调用的容器。
【解决方案3】:

一般来说,在 C\C++ 中,可用堆的最大数量在程序开始时并不固定——您始终可以通过直接使用 new/malloc 或使用 STL 容器来分配更多内存,例如stl::list,可以自己做。

【讨论】:

    【解决方案4】:

    我不认为问题出在内存上,因为 C++ 会获得所需的内存,甚至会占用 PC 上的所有可用内存。看看你是否delete 稍后访问的东西。

    【讨论】:

    • 我没有使用删除。我正在使用 std::map 中的擦除。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    相关资源
    最近更新 更多