1

I am encountering an error where the values of protected members of a base class are changing values between when the parent class constructor is called and when the child constructor is called. A stripped down version of the code is as follows:

Namespace A 
{
 class Parent
 {
  public:
   Parent (int a, int b, int c, int d);

  protected:
   std::vector<Eigen::Matrix<float, 3, 3, Eigen::RowMajor>> rmats_;
 }
}
A::Parent::Parent (int a, int b, int c, int d) {
 rmats_.reserve(3000);
 rmats_.clear ();
 Eigen::Matrix<float, 3, 3, Eigen::RowMajor> init_Rcam_ = Eigen::Matrix3f::Identity ();
 rmats_.push_back(init_Rcam_);
 std::cout << "size of rmats is " << rmats_.size() << std::endl;
}

Namespace B 
{
 class Child : public Parent
 {
  public:
   Child(int a, int b, int c, int d);
 }
}
B::Child::Child : A::Parent::Parent(a,b,c,d)
{
 std::cout << "size of rmats in the child is " << rmats_.size() << std::endl;
}

When a child object is created, the size in the parent constructor is reporting the expected size of 1, however the output in the child reports that the size of the vector is now 127101589483567331. there are also several other vectors of similar objects in the real code that all report incorrect sizes of vectors including another vector of size 1 changed to size 0 and a vector of size 3 changed to size 668637816.

I have tried with simpler version of the code using vectors of integers and get the expected results however the full code which does nothing additional between the two print cout statements state the size of the vector is changing between the parent constructor and the child constructor. Additionally the code appears to function properly under Linux using gcc, but breaks under windows using visual studio.

Are there any additional hidden steps that are taken during the construction process that would cause this error? Any compiler settings that may cause this type of issue?

Dale Wilson
  • 9,166
  • 3
  • 34
  • 52
James
  • 51
  • 7
  • 2
    Maybe I missed something. What is `A::parent` ? A typo for `A::Parent::Parent` ? – WhozCraig Mar 10 '15 at 16:59
  • 1
    There are at least two other problems: `child` vs `Child` and `B::Child`. – Mark B Mar 10 '15 at 17:01
  • Also, you define `B::child` and use `B::Child`. `B::Child : Parent(a,b,c,d){}` is not definition of the constructor you declared. – LogicStuff Mar 10 '15 at 17:03
  • I apologize a couple of typos, This code is a condensed version of the code that appears in serveral .cpp and .h files. they should be corrected now – James Mar 10 '15 at 17:11
  • While you are cleaning up the code, consider losing the namespaces. As it is, they add a lot of noise and "probably" don't contribute to the problem. If the problem goes away when the namespaces do, you have a clue. If they don't we get cleaner code to look at. – Dale Wilson Mar 10 '15 at 17:23
  • Can you please verify that this exact code snippet runs for you and reproduces the problem? – Kenny Ostrom Mar 10 '15 at 17:47
  • This code snippet illustrates the case as well as possible, but does not recreate the problem. – QuestionC Mar 10 '15 at 18:18

3 Answers3

1

According to the rules of construction in C++, the child constructor will always print a size of 1. The child's construction code simply does not execute until the parent's constructor is fully completed (more at C++: Construction and initialization order guarantees).

It looks like the Child class is using a garbage memory address for the vector.

Is it possible that Child.hpp and Parent.cpp are including different versions of the Parent.hpp file (you have a binary/header mismatch)?

Community
  • 1
  • 1
QuestionC
  • 10,006
  • 4
  • 26
  • 44
  • It appears to be using the correct versions of parent, which does come from another project). changes made to the parent class are reflected in the output of my code. The include directories from the project properties are also correct. Would there be anything else that would indicate a version mismatch? – James Mar 10 '15 at 17:29
  • Well, if you are rebuilding the child project but not rebuilding the parent project that would reflect changes to parent.hpp in the child class, but still result in binary compatibility issues. It's hard to diagnose without being over your shoulder. Can you try adding `cout << "address of rmats is " << &rmats_ << std::endl;` or something equivalent to the constructors in parent.cpp and child.cpp and clean+remake both projects? If &rmats is equal then you have memory stomping, if they're different, you have binary compatibility issues. – QuestionC Mar 10 '15 at 18:15
  • I did test the address of the objects for the parent and child and they both used the same address, so it must be memory stomping then. but it strange that the cout messages that i use are at the last lines of the parent constructor and the first lines of the child constructor, i even took everything out of the child constructor but the cout statements and the issue still occurs. – James Mar 10 '15 at 18:34
  • I have found the source of the problem and it is memory stomping, there are buffer allocations that happen before the print out statements. I tired disabling the allocations and the vectors are the correct size again in the child constructor. I am unsure why this error doesn't present itself until after the parent constructor has finished. Thank you for your help with this issue – James Mar 11 '15 at 12:01
0

Your constructor defintion is wrong, you have typos in your example and you do not call the base constructor correctly.

Your example compiles if you use the correct A::Parent::Parent(...) { } syntax for the parent contructor definition and B::Child::Child(...) : A::Parent(...) { } for the child constructor.

See it work in ideone.com

Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
  • The original code is written the way you describe and compiles fine, (I corrected the code above), the issue occurs when the code is run. As well just like the code you posted a simple version i wrote myself works just fine. I'm trying to figure out if something else occurs between the constructor for the parent and the constructor for the child that would affect the vector that is being used – James Mar 10 '15 at 17:17
  • Your example does not exhibit the problem then, because it works and prints 1 and 1 (a vector of doubles is not a vector of Eigen Matrices but the behaviour of the vector itself should be consistent). – Pixelchemist Mar 10 '15 at 17:23
  • I agree with you, the problem however is that the behavior that i am experiencing is not the same as the simple code, the code was to show what i am attempting to do in simple terms. I am trying to figure out why the vector appear to be valid in the parent constructor but point to garbage data in the child constructor which occurs directly after. – James Mar 10 '15 at 17:44
0

It breaks on windows only, using the production code similar to this, but this test snippit works correctly on windows and posix?

Check the Eigen library version installed on your windows box.

Check for anything weird happening to the std::vector when you destruct init_Rcam_ (which should be fine since the std::vector should have a copy)

Check for unrelated errors that can corrupt memory when exiting the A::Parent::Parent() constructor, but which seemed irrelevant when you were pulling out the working simplified code.

Kenny Ostrom
  • 5,639
  • 2
  • 21
  • 30
  • Both version use the most recent versions of Eigen, however deleting the init_Rcam_ objects causes a crash due to stack corruption. Also there are no errors that can see after exiting the constructor for the parent class(without destroying the init_Rcam_ object), Is there a way that i could see them or check for them in visual studio? – James Mar 10 '15 at 18:53