【问题标题】:what kind of problems can lack of deallocation cause?缺乏释放会导致什么样的问题?
【发布时间】:2012-07-04 20:10:01
【问题描述】:

如果我遇到了问题,我目前遇到了问题

*** glibc detected *** ./efit: free(): invalid next size (fast): 0x00000000006127f0 ***

带有glibc 错误的常用内存映射和回溯信息。但是,我无法找到此问题的原因。似乎(基本上)我的整个程序在发生这种情况时已经完成。我在网上读到的一件事是,这可能是由于缺乏释放。

现在,我一直在运行程序而没有释放我的一些数组(我的印象是释放会导致内存泄漏,但这只会影响程序运行时的性能和效率)。现在,当我重新启动程序时,我遇到了这个错误。

我之前执行的程序没有释放我的数组是否有可能“回来困扰我”,因为我试图写入之前执行的内存有未释放的内存?

如果不是,我完全被这个错误弄糊涂了。关于我应该从哪里开始寻找和/或我应该如何调试以找到它的任何线索?

为了它的价值,我正在使用 gfortran 编译

编辑: 虽然编译选项一开始并没有直接识别出这个问题,但它帮助我减少了它。我在do 循环中将整数变量iat 用于iat=1,natoms,然后几行之后,我认为iat1,natoms 的范围内描述了一个不同的整数。我正在引用数组边界之外的数组。当我更正了您的编译选项列出的一些警告时,这个错误变成了更清晰的错误描述:Fortran runtime error: Index '7' of dimension 1 of array 'isnormed' above upper bound of 6

是什么阻止了第一次产生这个错误?我所做的编译警告告诉我的唯一更改是更改 read(fout, '(a)'), line100' toread(fout, '(a)') line100' (删除逗号)并将旧样式字符描述 character*100 line100 更改为更新的 character(100) line100 描述.

【问题讨论】:

  • 您描述的一些警告/错误是编译时警告。当您编译源代码时,编译器会识别它们。 “高于上限”错误是运行时错误——直到您运行程序才发生。这就是为什么它没有出现在第一组警告/错误中的原因。运行时检查不是默认设置,因为它们会消耗 CPU 时间,但在开发程序时非常有用。
  • 我知道这一点,我的问题是在我进行这些编译时间更改之前,我遇到了运行时错误,但我从未收到“高于上限”错误 - 我只是得到了一个 @ 987654332@ 错误。我的问题是为什么进行这些简单的编译时警告更改会将glibc detected 错误变成“高于上限”错误。
  • 我无法解释,除非你一开始没有 -fcheck=all 选项。
  • 好吧,我没有,但正如你所说,所有这些选项都是编译时检查。它们都不是运行时错误检查选项,对吗?奇怪的是,在我更改了它给我的简单警告后,我得到了“高于上限”错误而不是glibc。正如我告诉我妻子的那样……就好像我在墙上画了一道划痕,它以某种方式神奇地固定了门!

标签: memory-leaks fortran glibc memory-management


【解决方案1】:

上一次运行程序的错误不会影响下一次运行。操作系统加载可执行文件的新版本并为其提供内存。只有当您让程序将信息写入文件并在下次运行时将其读入时,它们才能传输信息。

当程序完成时,操作系统会自动释放内存。此外,对于 Fortran >=95,当过程返回时,Fortran 会自动释放过程本地的可分配数组。

您很可能遇到内存使用问题,该问题正在破坏描述程序使用的内存的内部结构。对于 Fortran,这可以通过调用者和被调用者之间的参数不匹配、索引超出数组末尾或使用指针来实现。你在用指针吗?如果没有,前两个在这个时代通常很容易防范。将您的过程放入模块中并“使用”这些模块。这将允许编译器检查参数的一致性。使用下标的运行时检查选项进行编译。这将确定您是否在数组末尾进行索引并存储在其他内存中。

使用 gfortran,尝试以下编译器选项:-O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck=all -std =f2008 -pedantic -fbacktrace。如果其中一些识别出过多的警告,那么对于这个问题来说重要的是 fcheck=all,甚至更窄的 fcheck=bounds。

【讨论】:

    【解决方案2】:

    此消息与取消分配失败无关。这是说堆已损坏。发生这种情况的方式有很多,但忘记释放数组不是其中之一。如果这是 Fortran 代码,则很可能是一个错误声明的数组。

    glibc 进行一致性检查时正在生成该消息。因此何时消息出现(运行开始或结束)是不相关的,除非您知道损坏发生在消息出现之前的某个时间(但可能是任何时间)。

    损坏的堆意味着您的程序生成的答案可能从完全正确到完全无用。您必须删除此消息。

    (我的印象是解除分配会导致内存泄漏,但这只会影响程序运行时的性能和效率

    这是落后的。当释放没有完成时会发生内存泄漏。

    最好的方法是使用像valgrind 这样的工具,旨在详细检测和报告堆问题。

    【讨论】:

    • 谢谢,这就是我的意思——释放的缺乏会导致内存泄漏。对于它的价值,我是否正确,内存泄漏只会影响正在运行的程序,一旦它被终止,它就不再是问题了吗?
    • 内存泄漏就是它听起来的样子。机器具有固定数量的内存。如果您有泄漏,O/S 和运行时系统会认为分配了大块内存,而实际上您并没有使用它们。这意味着您的程序正在消耗它不需要的内存资源。结果可能是良性的(在现代工作站上使用 20K 而不是 10K 字节将完全不明显)到灾难(在 4Gb 机器上使用 8Gb 而不是 2Gb)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 1970-01-01
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多