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.