Multiply Defined Inline Constructors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have two C++ classes with identical constructor signatures. Each class has a distinct parent class. Both classes inline all of their member function definitions in the header file. The compiler does not generate the code inline, however. The loader defines only one constructor in the final executable; it appears to be the first one referenced in the set of object files. Recently this order changed in our build, leading to nastiness at runtime when virtual functions get called though pointers to the parent classes. 

I realize that simply changing the signature of one of the constructors will probably get around this. However, we have a large code base and the change will affect a lot of it; it is better avoided. In any case, future occurrences should be avoided.

If I make both of the constructors not inlined, then the loader emits double-definition errors. Is there any way to have the loader do the same for the inline case? If not, is there any way to force the loader to create separate instances? Is there any way to force the compiler to inline the code?

An example follows.

  --John Conley

//in parentA.h:
class parentA {
  public:
    parentA() {}
    virtual ~parentA() {}
    virtual int getType() = 0; 
  private:
};

class A : public parentA {
  public:
    A(int i) : myi(i) {
    printf("Constructing child of parentA\n");
    }
    ~A() {}
    int get() { return myi; }
    int getType() {return 12;}
  private:
    int myi;
};


//in parentB.h:
class parentB {
  public:
    parentB() {}
    virtual ~parentB() {}
    int getKind() { return 13; }
  private:
};

class A: public parentB {
  public:
    A(int i);: myi(i) {
      printf("Constructing child of parentB\n");
    }
    ~A() {}
    int get() { return myi; }
  private:
    int myi;
};

// in usesA.cc
void useA() {
  printf("Allocating  child of parentA\n");
  parentA* pa = new A(3);
  printf("parentA->getType() =  %d\n", pa->getType());
}

// in usesB.cc
void useB() {
  printf("Allocating  child of parentB\n");
  parentB* pb = new A(2);
  printf("parentB->getKind() = %d\n", pb->getKind());
}

//in main.cc:
extern void useA();
extern void useB();

int main() {
  useA();
  useB();
  return 1;
}

//output if linked "g++ usesA.o usesB.o main.o -o ab"
Allocating  child of parentA
Constructing child of parentA
parentA->getType() =  12
Allocating  child of parentB
Constructing child of parentA
parentB->getKind() = 13

//output if linked "g++ usesB.o usesA.o main.o -o ba" 
Allocating  child of parentA
Constructing child of parentB
Segmentation Fault (core dumped)

//The fault is on the call to getType, which is being called though the pointer to parentA 
//which points to the incorrectly constructed subclass of parentB.





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux