It seems there is a bug in the intel compiler version 130.
Here is the test program "intel_bug.c":
// This is the source code of icpc_bug.c #include <iostream> #include <sstream> using namespace std; class Table { public: Table() { } ~Table() { } protected: }; static int id = 0; class Use { public: Use() : forward_(this), back_(this), id_(id++) { std::cout << "Creating Use: "<< id_ << std::endl; } ~Use() { remove(); } Use(const Use& u) : id_(id++) { insert(u); std::cout << "after="<< str() << std::endl; } Use& operator=(const Use& u) { std::cout << "Use="<< str() << std::endl; if (this != &u) { remove(); insert(u); } return *this; } int size() const { int count = 0; const Use * ptr = this; do { count++; ptr = ptr->forward_; if (count > 100) { break; } } while (ptr != this); return count; } bool only() const { return this == this->forward_; } std::string str() const { std::stringstream ss; return ss.str(); } private: mutable const Use *forward_; mutable const Use *back_; int id_; void insert(const Use& u) const { this->back_ = &u; this->forward_ = u.forward_; u.forward_->back_ = this; u.forward_ = this; } void remove() const { this->forward_->back_ = this->back_; this->back_->forward_ = this->forward_; } }; class table_ptr_ex { public: explicit table_ptr_ex(Table* ptr = 0) : ptr_(ptr) { } ~table_ptr_ex() { if (use_.only()) delete (ptr_); } table_ptr_ex& operator=(const table_ptr_ex& other); private: explicit table_ptr_ex(Table* ptr, const Use& use) : ptr_(ptr), use_(use) {} Table *ptr_; Use use_; }; class LiteCalculator { public: LiteCalculator() {} ~LiteCalculator() {} void newTableEx(table_ptr_ex _tableEx); protected: table_ptr_ex tableEx_; }; table_ptr_ex& table_ptr_ex::operator=(const table_ptr_ex& other) { std::cout << "Assigning count: "<< use_.size() << " otherCount: "<< other.use_.size() << std::endl; if (&use_ != &other.use_) { const bool oldUseOnly = use_.only(); const Table* const oldPtr = ptr_; use_ = other.use_; ptr_ = other.ptr_; if (oldUseOnly) { delete (oldPtr); } } std::cout << "Finished Assigning count: "<< use_.size() << ""<< use_.str() << std::endl; return *this; } void LiteCalculator::newTableEx(table_ptr_ex _tableEx) { tableEx_ = _tableEx; } int main(int argc, char **argv) { table_ptr_ex tableToSend(new Table()); table_ptr_ex tableToSend2; for(int i=0;i<10;++i) { std::cout << "i: "<< i << std::endl; table_ptr_ex tmp = tableToSend; tableToSend2 = tmp; } return 0; }
The program compiled with icpc version 13 always core dump: lin260i2@devits3:~/ogd> which icpc /usr/local/intel/compiler130/composer_xe_2013_sp1.2.144/bin/ia32/icpc lin260i2@devits3:~/ogd> icpc icpc_bug.c -o icpc_bug lin260i2@devits3:~/ogd> icpc_bug Creating Use: 0 Creating Use: 1 i: 0 after= Assigning count: 1 otherCount: 2 Use= Finished Assigning count: 3 i: 1 after= Assigning count: 3 otherCount: 3 Use= Finished Assigning count: 1 i: 2 after= Assigning count: 1 otherCount: 2 Use= Finished Assigning count: 3 i: 3 after= Assigning count: 3 otherCount: 3 Use= Finished Assigning count: 1 i: 4 after= Assigning count: 1 otherCount: 2 Use= *** glibc detected *** double free or corruption (fasttop): 0x08450008 *** Aborted (core dumped)
The program works fine if I use g++ or intel compiler version 12.
It also works if I use -O0 when I compile the program.