Fortran 程序的 mtrace
我正在尝试使用 mtrace 来检测 Fortran 程序中的内存泄漏。 我正在使用 gfortran 编译器。 请参阅 wikipedia 条目,了解 mtrace 的(工作)C 示例: http://en.wikipedia.org/ wiki/Mtrace
我尝试了两种方法,即包装 mtrace() 和 muntrace() 并从 fortran 程序中调用它们,以及创建一个直接调用 mtrace() 和 muntrace() 的 C 程序,此外其间泄露的 Fortran 代码。 这两种方法都无法检测内存泄漏,但这里我仅介绍后者。
example.cleaky.f90
#include <stdlib.h>
#include <mcheck.h>
extern void leaky_(); // this might be different on your system
// if it doesn't work, try to run:
// 1) gfortran leaky.f90 -c
// 2) nm leaky.o
// and then change this declaration and its use below
void main() {
mtrace();
leaky_();
muntrace();
}
我用以下内容
subroutine leaky()
real, allocatable, dimension(:) :: tmp
integer :: error
allocate (tmp(10), stat=error)
if (error /= 0) then
print*, "subroutine leaky could not allocate space for array tmp"
endif
tmp = 1
!of course the actual code makes more...
print*, ' subroutine leaky run '
return
end subroutine leaky
进行编译:
gfortran -g example.c leaky.f90
然后我用以下内容运行:
export MALLOC_TRACE=`pwd`/raw.txt; ./a.out
然后我用以下内容解析 raw.txt
mtrace
输出:
mtrace a.out raw.txt
并得到:
无内存泄漏。
我是否做错了什么,或者我可以做些什么来让 mtrace 找到泄漏的 Fortran 内存分配? 我猜 gfortran 正在使用不同的 malloc
调用,而 mtrace
不会跟踪... 事实上,正如我上面所写,如果我编写一个 fortran main 来调用(包装的)mtrace()
和 muntrace()
,我会得到相同的结果。
编辑:我考虑了其他选项(包括一些此处尚未提及的选项),但是正在调试的实际代码在 P6/AIX 上运行,因此 Valgrind 会“只是”不方便(它需要在不同的机器上运行),而 Forcheck 则不方便(它需要在不同的机器上运行)并且昂贵(~ 3k$)。 目前 mtrace 如果有效的话将是最好的解决方案。
再次编辑: 我猜
我猜 gfortran 正在使用不同的
malloc
调用,而mtrace
不会跟踪...
是正确的。 查看可执行文件(使用 nm
或 readelf
),没有任何 malloc()
调用,但有 _gfortran_allocate_array
> 那些 - 可能会调用 malloc)。 还有其他想法吗?
再次编辑: 我发布了答案,但我无法接受它(转到 http://stackoverflow.uservoice。 com/pages/general/suggestions/39426 并请求该功能,它确实需要 - 不需要获得声誉)
I'm trying to use mtrace
to detect memory leaks in a fortran program. I'm using the gfortran compiler. See the wikipedia entry for a (working) C example of mtrace: http://en.wikipedia.org/wiki/Mtrace
I tried both ways, i.e. wrapping the mtrace() and muntrace() and call them from the fortran program, as well as create a C program which directly call the mtrace() and muntrace(), besides the leaking fortran code in between.
Both approaches will fail to detect the memory leak, but here I'm presenting only the latter.
example.c
#include <stdlib.h>
#include <mcheck.h>
extern void leaky_(); // this might be different on your system
// if it doesn't work, try to run:
// 1) gfortran leaky.f90 -c
// 2) nm leaky.o
// and then change this declaration and its use below
void main() {
mtrace();
leaky_();
muntrace();
}
leaky.f90
subroutine leaky()
real, allocatable, dimension(:) :: tmp
integer :: error
allocate (tmp(10), stat=error)
if (error /= 0) then
print*, "subroutine leaky could not allocate space for array tmp"
endif
tmp = 1
!of course the actual code makes more...
print*, ' subroutine leaky run '
return
end subroutine leaky
I compile with:
gfortran -g example.c leaky.f90
Then I run with:
export MALLOC_TRACE=`pwd`/raw.txt; ./a.out
Then I parse the raw.txt
mtrace
output with:
mtrace a.out raw.txt
and get:
No memory leaks.
Is there anything I'm doing wrong, or something I can do to let mtrace
find the leaky fortran memory allocation? I guess gfortran is using a different malloc
call, which mtrace
does not trace...
In fact, as I wrote above I get the same result if I write a fortran main which would call the (wrapped) mtrace()
and muntrace()
.
EDITED: I considered other options (including some not yet mentioned here), but the actual code being debugged runs on P6/AIX, so Valgrind would be "just" inconvenient (it needs to run on a different machine), whereas Forcheck would be inconvenient (it needs to run on a different machine) and expensive ( ~ 3k$). At present mtrace would be the best solution, if it worked.
EDITED again:
My guess
I guess gfortran is using a different
malloc
call, whichmtrace
does not trace...
was correct. Looking into the executable (either with nm
or readelf
) there isn't any malloc()
call, but _gfortran_allocate_array
ones - which maybe will call malloc). Any other ideas?
EDITED again:
I posted the answer but I cannot accept it (go to http://stackoverflow.uservoice.com/pages/general/suggestions/39426 and request the feature, it's really needed - no reputation gain wanted)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我不是 mtrace 方面的专家,所以我无能为力。 如果您使用的是受支持的系统,我建议您尝试使用 valgrind 工具来查找内存泄漏。 使用 valgrind 查找内存泄漏就像调用 valgrind --leak-check=full ./a.out 一样简单。
I'm not an expert on mtrace, so I can't help with that. I would suggest that you try the valgrind tool to find memory-leaks if you are using a supported system. Using valgrind for finding memory-leaks is as simple as calling
valgrind --leak-check=full ./a.out
.Valgrind 仅适用于 Linux。 对于 Windows 产品,请查看 Forcheck。
http://www.forcheck.nl/features.htm
Valgrind is Linux only. For a windows product look at Forcheck.
http://www.forcheck.nl/features.htm
Steve Kargl 给出了答案,简单地说,mtrace 没有发现任何泄漏,因为如果编译器符合标准,则不会出现任何泄漏:请参阅 http://gcc.gnu.org/ml/fortran/2008-11/msg00163.html 了解详细信息。
事实上,我不是一个伟大的 Fortran 专家(我主要是 C/C++/java 人),而且我还使用了另一个编译器,它在这种情况下确实会泄漏(我没有提到这一点是为了让问题更容易)。 因此我错误地认为 gfortran 也存在泄漏,但事实并非如此(我检查了 top)
Steve Kargl had the answer, which briefly is that mtrace does not find any leak, because there isn't any leak if the compiler conforms to the standard: See http://gcc.gnu.org/ml/fortran/2008-11/msg00163.html for details.
In fact I'm not a big fortran expert (I'm mostly C/C++/java guy), and I was also using another compiler, which DOES leak in such a condition (I didn't mention that to keep the question easier). Thus I mistakenly thought that the leak was there also with gfortran, which is not the case (I checked with top)
我有调试 Fortran 程序的经验,但说实话我无法真正理解你的问题。 我认为这是因为我没有太多与 Fortran 不同的 C/C++ 调试经验。 尽管如此,我认为这将使您受益:
使用具有以下编译选项的英特尔编译器将检测到几乎所有内存泄漏、错误的地址访问或在运行时使用未初始化的指针/变量。
英特尔:
-O0 -debug -traceback -check -ftrapuv
对于 Gfortran 来说,使用这些编译器选项几乎可以得到上述任何错误。
gfortran:
-g -O0 -fbounds-check -Wuninitialized
它将打印子例程调用的回溯,直到发生错误。 使用两个不同的编译器进行编译总是有帮助的,根据我的经验,此后几乎不会出现内存泄漏。
I have experience with debugging Fortran programs but to be honest I could not really understand your question. I think it is because I do not have much of C/C++ debugging experience which different to Fortran. Nevertheless I think this will benefit you:
Using the Intel compiler with the following compile options will detect almost any memory leak , wrong address access or using uninitialized pointer/variable during runtime.
intel:
-O0 -debug -traceback -check -ftrapuv
For Gfortran also you can pretty much get any of the above errors with these compiler options.
gfortran:
-g -O0 -fbounds-check -Wuninitialized
It will print the traceback of subroutine calls until where the error occurs. It is always helpful to compile with two different compilers and in my experience you will have almost no memory leak after this.