1

I'm relatively new to c++ and am confused by some strange behavior. I get an object which contains an std::vector. Then, I print out its size twice, by exactly the same copied line:

    Pose& pose = getCurrentPose();
    std::cout << "nr1: " << pose.transforms.size() << " bones." << std::endl;
    std::cout << "nr2: " << pose.transforms.size() << " bones." << std::endl;

The result:

Nr1: 17 bones.
Nr2: 38294074 bones.

Any further calls to this vector's size returns the same huge number (17 should be right).

I also get errors when iterating over the vector. It seems to me that it hasn't actually resized, but that some kind of end-pointer got corrupted. What is happening here and how can I solve this problem?

Here is what getCurrentPose roughly looked like:

Pose& getCurrentPose() {
    Pose& accu;

    for (int b = 0; b < p.transforms.size(); b++) {
        BoneState bs;
        accu->transforms.push_back(bs);
    }

    for (int b = 0; b < p.transforms.size(); b++) {
        accu->transforms.at(b).loc += getLoc(b);
        accu->transforms.at(b).rot += getRot(b);
        accu->transforms.at(b).scale += getScale(b);
    }

    return accu;
}

I am also not multi-threading anywhere as far as I know. This is an OpenGL-application, which may be related.

Erik Brendel
  • 683
  • 9
  • 23

1 Answers1

5

My bet is that GetCurrentPose() looks dangerously like this.

Pose & GetCurrentPose()
{
  Pose p;
  p = something_magic();
  return p;
}

or, following your own answer...

Pose * GetCurrentPose()
{
  Pose p;
  p = something_magic();
  return &p;
}

Both are a surefire recipe for chaos, returning pointers and references to objects which have left scope.

The right approach for this is typically return-by-value. If Pose objects aren't copyable for some reason, you need to think through your whole design very carefully.

Pose GetCurrentPose()
{
  Pose p;
  p = something_magic();
  return p;  // theoretically this returns a copy of p, but the compiler can optimise out the copying step.
}
Roddy
  • 66,617
  • 42
  • 165
  • 277
  • It looked very much like your first guess... Why is this dangerous? Why can't I create a new object this way and return it (or its pointer) in c++? – Erik Brendel Jun 09 '16 at 15:59
  • @ErikBrendel - You can return 'it' (or, more precisely, a copy of it) but not a pointer/reference to it, because the object to which your pointer refers is destroyed when the function exits. – Roddy Jun 09 '16 at 16:02
  • Isn't that unnecessary copying overhead? Why create an object to only return a copy of it, if the original isn't needed for anything else? – Erik Brendel Jun 09 '16 at 16:07
  • The copying (if it happens) is completely invisible to you, and compilers are allowed to optimize it out (google NRVO). To understand why the copy is necessary, you need to know how (and where) objects are created on the stack, and how the calling function expects to receive the object that's returned to it. – Roddy Jun 09 '16 at 16:12
  • @ErikBrendel Don't worry, your compiler is gonna be asking itself the same thing once it compiles the code, and "ellide" the copy for you. You don't have to worry about the performance, the machine can do it for you – KABoissonneault Jun 09 '16 at 16:12
  • wow i didn't know that compilers were this good at optimizing. Thanks for the insight. Return-by-value obviously work like a charm. – Erik Brendel Jun 09 '16 at 16:18