【问题标题】:Freeing memory issue causing my c program to crash but it doesn't crash while debugging?释放内存问题导致我的 c 程序崩溃但在调试时不会崩溃?
【发布时间】:2012-04-11 23:44:43
【问题描述】:

我以前在使用同一个程序时遇到过麻烦,因为它会分配大量内存。我摆脱了大多数问题,但我仍然遇到一个特定问题。当我在 Eclipse 中运行我的程序时,它编译得很好,但它会因这条消息而崩溃

*** glibc detected *** /home/user/workspace/TTPrueba/Debug/TTPrueba: free(): invalid pointer: 0xb6bc0588 ***

当我用 Valgrind 运行它时,它告诉我这个

==31580== Process terminating with default action of signal 11 (SIGSEGV)
==31580==  Access not within mapped region at address 0x0
==31580==    at 0x804BEA3: termino (Menu.c:899)
==31580==    by 0x804BE05: computar_transformadas (Menu.c:840)

所以问题是它试图释放一个无效的内存地址,但是我在调​​试模式下一步一步地去,程序永远不会崩溃!!!! :(

知道为什么会发生这样的事情吗?为什么它在调试时工作但在运行时不工作?这是非常奇怪的行为。

for(phi=0;phi<360;phi++){

      for(j=0;j<par.param1[phi][0];j++){


              for(o=0;o<(par.prueba[phi][j][1]-par.prueba[phi][j][0]);o++){//AQUI 849

                 free(par.pixels[phi][j][o]);//HERE IS LINE 899 WHERE IT ALWAYS CRASHES

                 if(o==(par.prueba[phi][j][1]-par.prueba[phi][j][0]-1))
                     free(par.pixels[phi][j]);

              }


          free(par.prueba[phi][j]);

      }

感谢您的帮助!

【问题讨论】:

  • 啊。可爱的——在它的自然栖息地中,还不够几乎稀有——Heisenbug。看到羽毛美丽的迷彩图案了吗?那是什么?你看不见吗?嗯,是。这就是你知道它在那里的方式。
  • 在调试器中内存可能为零,但在您的程序中可能并非如此。尝试将您的 malloc 更改为 calloc。
  • “我在调试模式下一步一步走,程序永远不会崩溃!!!!” - 欢迎来到调试的世界!
  • 你没有显示你的 malloc 代码...
  • 为什么在第三个 for 循环中使用 if(o==...) free()?

标签: c debugging memory crash valgrind


【解决方案1】:

一个可能的原因 - 调试器可能正在更改事物的内存布局,因此当内存损坏时,它恰好位于“不碍事”的地方。

或者调试器可能会导致分配的内存归零,这可能不会在生产运行中发生。

【讨论】:

  • 或使用调试器在断点处停止的隐式同步正在改变线程的时序交互......(如果是多线程的)
  • 不是多线程的,所以这不是问题。我认为一些统一的值是问题所在。
【解决方案2】:

这并不奇怪。例如,如果 par.pixels[phi][j][o] 未初始化。它可以包含任何东西,在调试器环境中,你有不同的内存布局 par.pixels[phi][j][o] 可能会变成 0,所以 free 没有崩溃。

【讨论】:

  • 除了使用 calloc (确保指针最初设置为 NULL,任何试图错误地取消引用它们的尝试都很明显),在释放它们指向的内存后将指针设置为 NULL 是一个好习惯(对于同样的原因)。或者有时在调试时,会在错误消息/调试打印中突出显示“毒”值(例如,0xdeadbeefdeadbeef)。
  • 我该怎么做?例如,如果我做 free(par.pixels[phi][j][o]);之后我应该做点什么吗?
  • 如果您从未初始化它,您将无法修复它。检查它的来源,它必须从 malloc() 分配一个结果才能成为有效的 free() 候选对象。
  • 问题:如果 par.pixels[phi][j][o] 是有符号的 int 并且它所持有的值大于 32767 会在释放内存时引起问题吗?跨度>
  • par.pixels[phi][j][o] 不应该是有符号整数,它应该是指针类型,它应该包含之前 malloc() 调用的返回值。值并不重要。
【解决方案3】:

我看到的一个问题是你释放了par.pixels[phi][j][o],其中o 从零开始循环,然后访问 par.pixels[phi][j][0],它刚刚被释放了!

您还释放了 par.pixels[phi][j],但继续循环访问 par.pixels[phi][j] 并释放不再有效的指针。

【讨论】:

  • 在释放 par.pixels[phi][j][o] 后我从不访问 par.pixels[phi][j][0] 我访问 par.prueba[phi][j][0 ].
  • 另外,当我释放 par.pixels[phi][j] 时,我会确保它是最后一个循环,所以下一个循环会从中出来并停止释放内存
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多