virtual destructor not called with first private clause

General OpenMP discussion

virtual destructor not called with first private clause

Postby ciccio » Thu May 22, 2008 6:02 am

Hi,

I recently discovered the following memory leak in my openmp code.
When a class it's destructor is a virtual (due to inheritance) and an object of that class type is used as a first private, then the destructor is not called.

Is this behavior normal, as far as I know, I don't think so.

Here is a very simple example code.
Code: Select all
#include <iostream>

class array {
public :
  array(void) : ptr(NULL), l(0){ };
  array(const array &c): l(c.l) {
    ptr = new double [l];
    std::cout << "copy construct pointer : " << ptr << std::endl;
  };
  array(size_t L): l(L) {
    ptr = new double [l];
    std::cout << "construct pointer : " << ptr << std::endl;
  }

  virtual ~array(void) {
    std::cout << "destroy ptr : " << ptr << std::endl;
    delete [] ptr;
  }

private :
  double *ptr;
  size_t l;
};


int main(void) {
  array tmp(100);
#pragma omp parallel for firstprivate(tmp1)
  for (int a = 0; a >= 0; --a) {
  }
  return 0;
}


Below you find the compilation and valgrind output (mark that tmp has a size of 1600 bytes). The problem is ran on a dual core system.

Code: Select all
[ openmp]$ g++ -ggdb --openmp firstprivate.cpp
[ openmp]$ ./a.out
construct pointer : 0x602010
copy construct pointer : 0x602540
copy construct pointer : 0x602870
destroy ptr : 0x602010
[ openmp]$ valgrind --leak-check=full --show-reachable=yes ./a.out
==7319== Memcheck, a memory error detector.
==7319== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==7319== Using LibVEX rev 1804, a library for dynamic binary translation.
==7319== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==7319== Using valgrind-3.3.0, a dynamic binary instrumentation framework.
==7319== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==7319== For more details, rerun with: -v
==7319==
construct pointer : 0x5f35298
copy construct pointer : 0x5f35878
copy construct pointer : 0x5f35bc8
destroy ptr : 0x5f35298
==7319==
==7319== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 3 from 1)
==7319== malloc/free: in use at exit: 1,928 bytes in 4 blocks.
==7319== malloc/free: 8 allocs, 4 frees, 3,432 bytes allocated.
==7319== For counts of detected errors, rerun with: -v
==7319== searching for pointers to 4 not-freed blocks.
==7319== checked 8,585,888 bytes.
==7319==
==7319== 24 bytes in 1 blocks are still reachable in loss record 1 of 3
==7319==    at 0x4C1ED1B: malloc (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so)
==7319==    by 0x4C1EE64: realloc (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so)
==7319==    by 0x53AB288: (within /usr/lib64/libgomp.so.1.0.0)
==7319==    by 0x53AD4A0: (within /usr/lib64/libgomp.so.1.0.0)
==7319==    by 0x400D41: main (firstprivate.cpp:26)
==7319==
==7319==
==7319== 304 bytes in 1 blocks are possibly lost in loss record 2 of 3
==7319==    at 0x4C1DE2C: calloc (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so)
==7319==    by 0x400FE62: _dl_allocate_tls (dl-tls.c:300)
==7319==    by 0x57C3B41: pthread_create@@GLIBC_2.2.5 (in /lib64/libpthread-2.7.so)
==7319==    by 0x53AD3BE: (within /usr/lib64/libgomp.so.1.0.0)
==7319==    by 0x400D41: main (firstprivate.cpp:26)
==7319==
==7319==
==7319== 1,600 bytes in 2 blocks are definitely lost in loss record 3 of 3
==7319==    at 0x4C1F1F7: operator new[](unsigned long) (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so)
==7319==    by 0x400EF7: array::array(array const&) (firstprivate.cpp:7)
==7319==    by 0x400D84: main.omp_fn.0 (firstprivate.cpp:28)
==7319==    by 0x400D4A: main (firstprivate.cpp:26)
==7319==
==7319== LEAK SUMMARY:
==7319==    definitely lost: 1,600 bytes in 2 blocks.
==7319==      possibly lost: 304 bytes in 1 blocks.
==7319==    still reachable: 24 bytes in 1 blocks.
==7319==         suppressed: 0 bytes in 0 blocks.


When removing the virtual tag from the destructor, the leak vanishes and the output makes more sense.
Code: Select all
[ openmp]$ ./a.out
construct pointer : 0x602010
copy construct pointer : 0x602540
destroy ptr : 0x602540
copy construct pointer : 0x602540
destroy ptr : 0x602540
destroy ptr : 0x602010


The two leaks of 24 and 304 bytes are probably due to a bug in g++ (see viewtopic.php?f=3&t=128).

Is the behavior addressed above correct or is it again a bug?
ciccio
 
Posts: 8
Joined: Tue Jan 29, 2008 6:57 am

Re: virtual destructor not called with first private clause

Postby ejd » Thu May 22, 2008 7:05 am

The OpenMP V2.5 spec wasn't very clear about when destructors were called. Hopefully the OpenMP V3.0 spec makes it more clear. Unfortunately, since it was not as clear as it should have been, many implementations delayed or "forgot" to call the destructors. The information you have shown indicates that the destructor was called for each of the blocks constructed. However, the Valgrind report shows that storage has been lost. When I run this with our implementation on Solaris I am also seeing some storage lost. In the past, when I have looked at some of these reported losses, I have found that most of them have been due to the tools not being able to correctly keep track of the storage and are false reports. As before, I am afraid that my best suggestion is to ask this question in the gcc forums where the implementors of gcc can look at the code and best answer the question.
ejd
 
Posts: 1025
Joined: Wed Jan 16, 2008 7:21 am

Re: virtual destructor not called with first private clause

Postby jakub » Thu May 22, 2008 4:24 pm

You've just discovered a g++ bug. If the destructor is not virtual, it works correctly. I'll look into this tomorrow. If you could file a bug at http://gcc.gnu.org/bugzilla/ with openmp as keyword, I'd appreciate it.
jakub
 
Posts: 74
Joined: Fri Oct 26, 2007 3:19 am

Re: virtual destructor not called with first private clause

Postby jakub » Fri May 23, 2008 7:02 am

jakub
 
Posts: 74
Joined: Fri Oct 26, 2007 3:19 am


Return to Using OpenMP

Who is online

Users browsing this forum: Yahoo [Bot] and 10 guests