views:

618

answers:

7

By instantiating an object in C++ with the following class I get a segmentation fault or aborts, depending on the order declaring member variables. E. g. putting mMemberVar and mAnotherMemberVar after mAnotherCountVar results in a segfault. From this listing I removed a std::ofstream from the member variables, which caused the segmentation fault independent of its position.

I think the order is not directly the problem, but what do you think could the reason be? This class is part of a huge project, but this in this class is the place, where the error appeared the first time.

class COneClass : public IInterface
{
public:

  COneClass();

  virtual ~COneClass();

  static const unsigned int sStaticVar;
  static const unsigned int sAnotherStaticVar;


private:
  COneClass();
  COneClass(const COneClass& );
  COneClass& operator=(const COneClass& );

  int mMemberVar;
  int mAnotherMemberVar;
  bool mIsActive;
  bool mBoolMemberVar;
  bool mAnotherBoolMemberVar;
  unsigned int mCountVar;
  unsigned int mAnotherCountVar;
};

COneClass::COneClass() :
  mMemberVar(0),
  mAnotherMemberVar(0),
  mIsActive(false), 
  mBoolMemberVar(false),
  mAnotherBoolMemberVar(false),
  mCountVar(sStaticVar),
  mAnotherCountVar(sAnotherStaticVar)
{
}
+2  A: 

I think the whole class is not directly the problem. Can you produce a minimal code that crashes just by using this class? It seems to me that the problem is somewhere else in your code base.

However, you may add a bool Invariant() const; function to that class and call it (only in debug builds) with assert(Invariant()); at the end of your constructor and on entering and exiting all your public functions. This might help you to "crash early, crash often" and hence point you to some of the problematic code.

Daniel Daranas
+3  A: 

the class members are initinised by the order they are declared. the order in the init list does not matter. In your case it's this order: mMemberVar -> mAnotherMemberVar -> mIsActive -> mBoolMemberVar -> mAnotherBoolMemberVar -> mCountVar -> mAnotherCountVar;

t.g.
you said"order in the init list does not matter" , this seems wrong to me
sat
@SSS: No it is not wrong: "Both base class objects and member data objects are initialized in declaration order, regardless of the order in the initialization list in the constructor definition." (http://codewrangler.home.comcast.net/~codewrangler/tech_info/ctor_init.html#InitializationOrder)
fretje
@fretje : it seems i was wrong and you are correct, I will do more home work and will get back to you soon.Thank for your comment, Otherwise i would have always thought like that
sat
@fretje : mem-initialization lists are processed by the compiler , so you can not guarantee
sat
@SSS: this is guaranteed by the C++ standard, not compiler specific. See here:informit.com/guides/…. Danny usually talks about standard C++ only.
t.g.
Expanding on what SSS has said -- the reason is simple although maybe not intuitive: when the object is destructed the destructors for any member objects have to be called in reverse order of construction. Because you can have 2 or more constructors with different initialisation lists you can't use the initialisation list to define the construction order, so the only fixed order -- i.e. the order of declaration in the class definition -- is used. (c.f. Scott Meyer, Effective C++, item 13.)
AAT
A: 

There's nothing in the code you've posted which is in any way abnormal. Either something in the IInterface constructor is failing, or something else entirely is going wrong. Perhaps you've a buffer overflow somewhere which is reading the data you've changing the structural order of.

Pete Kirkham
+4  A: 

Perhaps it is a case of the "static initialization order fiasco", http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.16, as a result of initializing mCountVar and mAnotherCountVar with static members?

You could init to zero in the list and then assign in the body of the constructor.

Neil
+2  A: 

Could be "static initialization order fiasco" judging by the fact that you have public static variables and a private constructor (speaking of which how can you have a public and private definition of the constructor???). These signs indicate the possibility that there is a dependency with other classes here.

Timothy Pratley
+1  A: 

The members’ constructors are called before the body of the containing class’ own constructor is executed. The constructors are called in the order in which they are declared in the class rather than the order in which they appear in the initializer list.

To avoid confusion, it is best to specify the initializers in declaration order.

The member destructors are called in the reverse order of construction every thing work properly

class MyClass//**1: mem-init**
{
private:
long number;
bool on;
public:
MyClass(long n, bool ison) : number(n), on(ison) {}
};

MyClass(long n, bool ison) //2 initialization within constructor's body
{
number = n;
on = ison;
}

There is no substantial difference between the two forms in the case of MyClass's constructor. This is due to the way mem-initialization lists are processed by the compiler. The compiler scans the mem-initialization list and inserts the initialization code into the constructor's body before any user-written code. Thus, the constructor in the first example is expanded by the compiler into the constructor in the second example. Nonetheless, the choice between using a mem-initialization list and initialization inside the constructor's body is significant in the following four cases:

l Initialization of const members l Initialization of reference members l Passing arguments to a constructor of a base class or an embedded object l Initialization of member objects

sat
+1  A: 

This doesn't look like your real code. But be aware in your real code, that class members are constructed in the order they are defined in the class, REGARDLESS of the order of the initializer list in the constructor. Given that you mention changing the order of the members in the class affects the problem, this might be what's wrong. For example, your code might do something like this:

class MyClass {
public:
    const int member1;
    const int member2;
    MyClass() {
      : member2(0),
      : member1(member2) // ERROR: this runs first because member1 is defined first
                      // member2 not yet constructed; assigns undefined value to member1
    {}
};
AshleysBrain