使用OpenMP编译会导致内存泄漏。

3
根据valgrind的结果,我可以在使用OpenMP编译一个简单的hello-world程序时引发内存泄漏。这似乎没有意义,因为hello-world程序并没有故意使用任何OpenMP功能。
假设下面的程序命名为hi.c并按照以下方式编译: $ gcc -o hi hi.c GCC版本为4.8.3。
#include <stdio.h>

int main( void )
{
  printf( "hi\n" );
  return 1;
}

我们应该期望从valgrind得到一个泄漏报告来验证显而易见的结果:没有内存泄漏。我的观察与这个假设相符:
$ valgrind --tool=memcheck ./hi
==13064== Memcheck, a memory error detector
==13064== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==13064== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==13064== Command: ./hi
==13064== 
hi
==13064== 
==13064== HEAP SUMMARY:
==13064==     in use at exit: 0 bytes in 0 blocks
==13064==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==13064== 
==13064== All heap blocks were freed -- no leaks are possible
==13064== 
==13064== For counts of detected and suppressed errors, rerun with: -v
==13064== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

我希望在使用其他标志编译后也能收到相同的报告。但是,情况并非如此。当我使用-fopenmp标志进行编译时,观察到存在内存泄漏问题。

$ gcc -fopenmp -o hi hi.c

$ valgrind --tool=memcheck ./hi
==13084== Memcheck, a memory error detector
==13084== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==13084== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==13084== Command: ./hi
==13084== 
hi
==13084== 
==13084== HEAP SUMMARY:
==13084==     in use at exit: 8 bytes in 1 blocks
==13084==   total heap usage: 2 allocs, 1 frees, 32,824 bytes allocated
==13084== 
==13084== LEAK SUMMARY:
==13084==    definitely lost: 0 bytes in 0 blocks
==13084==    indirectly lost: 0 bytes in 0 blocks
==13084==      possibly lost: 0 bytes in 0 blocks
==13084==    still reachable: 8 bytes in 1 blocks
==13084==         suppressed: 0 bytes in 0 blocks
==13084== Rerun with --leak-check=full to see details of leaked memory
==13084== 
==13084== For counts of detected and suppressed errors, rerun with: -v
==13084== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

有人知道为什么使用OpenMP编译会导致内存泄漏吗?虽然此程序没有调用OpenMP,但我希望在将来使用它时能确保正确处理内存。


哪个版本的 gcc?无法在 4.4.7 中重现。 - Grzegorz Szpetkowski
我正在使用GCC 4.8.3版本。我编辑了帖子以包括版本号。 - jdmartin86
libgomp(GNU OpenMP运行时库)与Valgrind的memcheck存在已知问题,简单的谷歌搜索就可以找到几篇解释。同时,熟悉一下Stack Overflow的搜索功能(位于页面右上角)也是个不错的选择,因为您并不是第一个在这里提出同样问题的人。 - Hristo Iliev
无论您使用哪种语言,GCC都使用libgomp实现OpenMP。如果您仔细查看其他问题,您会看到这个:by 0x62263DF: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)。这不是泄漏,另一个问题的答案链接到的手册中已经解释了这一点。实际原因很复杂,在这里有详细说明。 - Hristo Iliev
显示剩余2条评论
1个回答

3

那个valgrind报告并没有描述一个内存泄漏。程序退出时仍然存在分配的堆内存是可访问的。

很可能你的编译器的openmp实现会向你的程序注入一个全局变量,并导致它在程序启动时(即在main()之前)作为动态分配的一部分。


谢谢您的回复。让我看一下编译器的输出来验证您的答案。 - jdmartin86
修改为将“static”更改为“global”。 - John Bollinger
不是编译器,而是OpenMP运行时库libgomp.so的构造器之一注入了一个TLS键,该键会一直保留到进程终止的最后时刻。 - Hristo Iliev
@HristoIliev:好的,但我认为libgomp.so是gcc OpenMP实现的一部分。当然,它与编译器本身是分开的,但你通常不需要知道它或显式地链接它。可能会有所不同。 - John Bollinger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接