- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Consider the following contrived code:
[cpp]#include#include #include using namespace std; class foo { public: foo(int v=0) : _bar(v){} ~foo() {cout << "destructing: " << _bar << endl;} int Bar() {return _bar;} private: int _bar; }; int main() { foo g(5); foo f(99); #pragma omp parallel for default(none) shared(std::cout) private(f) num_threads(3) for (int i=0; i<3; i++) { usleep(omp_get_thread_num()*1e6); cout << omp_get_thread_num() << ": " << f.Bar() << endl; } } [/cpp]
- With this code, g++ and icpc produce identical results. Here each instance of f inside the loop is instantiated with the default constructor (as each of the _bar values is seen to be the default value of 0)
0: 0
destructing: 0
1: 0
destructing: 0
2: 0
destructing: 0
destructing: 99
destructing: 5
icpc produces:
0: 0
destructing: 0
1: 0
destructing: 0
2: 0
destructing: 0
destructing: 99
destructing: 5
- Now change the private clause on line 24 to firstprivate. We see that instantiation now occurs with the implicit copy constructor (as _bar is 99). But, for the icpc case none of the private copies of f get destructed!
0: 99
destructing: 99
1: 99
destructing: 99
2: 99
destructing: 99
destructing: 99
destructing: 5
icpc produces:
0: 99
1: 99
2: 99
destructing: 99
destructing: 5
Version info:
icpc (ICC) 12.1.0 20111011
g++44 (GCC) 4.4.4 20100726 (Red Hat 4.4.4-13)
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Did you try to declare the destructor as 'virtual'?
classfoo
{
public:
...
virtual ~foo(){ cout<<"destructing:"<<_bar<
};
I know that it sounds as astrange advice because there areNo Runtime Binding in your Test-Case. Anyway, I would try.
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I just tried re-running with a virtual destructor, but it did not change the results.
-Griffin
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As a workaround you may add 'lastprivate(f)' to 'firstprivate(f)', then all destructors are called as they should. Because without the lastprivate clause the value of f has an indeterminate value upon exit from the construct, this workaround does not affect any code after the work-sharing construct.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would also check the code with commented out '#pragma openmp ...' directive and lines 25 to 29 in
order to see that the C/C++ compiler does everything well and destructors are called.
Another verification before claiming that "this is a bug" is a Test-Case for a Runtime Binding of C++
objects. I had some issues with g++ version 3.4.2 in the past.
Best regards,
Sergey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'll test without the #pragma, but I've never had any issues of not having destructors called and the code does call the destructor when the variable is private.
FWIW, I've tested this under Windows running Visual Studio 2008 with the Intel Compiler plugin turned on and the results are the same.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
class A
{
public:
A( void ){ printf( "A::A\n" ); };
virtual ~A( void ){ printf( "A::~A\n" ); };
};
class V
{
public:
V( void ){ printf( "V::V\n" ); };
virtual ~V( void ){ printf( "V::~V\n" ); };
//~V( void ){ printf( "V::~V\n" ); };// If it is declared as Non Virtual ~W() won't be called and
}; // "resources" won't be released
class W : public V
{
public:
W( void ){ printf( "W::W\n" ); };
virtual ~W( void ){ printf( "W::~W\n" ); };
//~W( void ){ printf( "W::~W\n" ); };
};
void main( void )
{
A *pA = new A();
printf( "\n" );
V *pv = new V();
delete pv; // pv->~V::V(); // Used ::operator delete()
printf( "\n" );
pv = new W();
delete pv; // pv->~W::W(); // Used W::operator delete()
printf( "\n" );
pv = new W();
::delete pv;// pv->~W::W(); // Used ::operator delete()
printf( "\n" );
delete pA;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is to verify that a C/C++ compiler produces everything right without OpenMP. Especially, such a
fundamental thing as calling a virtual destructor.
This is not a text-book example. I have several tests for virtual destructors in my set of Test-Cases. I
usethese Test-Casesbecause in our Build Environment four different C/C++ compilers are used and
two more are coming. It allows to verify that regardless of a C/C++ compiler, or OpenMP in your case,
there are no bugs and Test-Cases produce absolutely identical outputs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To intel staff: please create a ticket for fixing this bug ("objects created for OpenMP work-sharing constructs with 'firstprivate' clause are not destructed"), a test case is supplied with the first post by Griffin Myers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I will have a look into this. From your description, it seems that the compiler indeed does not fully respect the OpenMP spec. I will check with our compiler team about a solution.
Cheers,
-michael
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1. #pragma omp parallel for default( none ) shared( std::cout ) private( f ) num_threads( 3 )
>> g++ produces << >> VS 2005 produces <<
0: 0 0: 0
destructing: 0 destructing: 0
1: 0 1: 0
destructing: 0 destructing: 0
2: 0 2: 0
destructing: 0 destructing: 0
destructing: 99 destructing: 99
destructing: 5 destructing: 5
2. #pragma omp parallel for default( none ) shared( std::cout ) firstprivate( f ) num_threads( 3 )
>> g++ produces << >> VS 2005 produces<<
0: 99 0: 99
destructing: 99 destructing: 99
1: 99 1: 99
destructing: 99 destructing: 99
2: 99 2: 99
destructing: 99 destructing: 99
destructing: 99 destructing: 99
destructing: 5 destructing: 5
PS1: My modifications to the Test-Case are as follows:
1.
//#include
2.
Instead of
usleep( omp_get_thread_num() * 1e6 );
I used
::Sleep( omp_get_thread_num() * 1e3 );
PS2: Memory Leaks are NOT detected.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page