1

I am now working on a rather complex project involving control of a simulated robotic arm. I finished a first version of the project and it is working fine. I just added some new code that collect some information about the system at each iteration, save it in some arrays, and at the end prints everything in a file for later analysis.

Now, something real strange is happening. If I define the file in which the data will be saved as follow:

const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\ta";

everything works fine, exactly the same as it did before I add the new code (plus saving the data).

But if I define it as follow:

const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\tacit.txt";

then the system behaves in another way. Does not crash, but the robotic arm moves differently.

I tried to comment all the code that was making use of SAVEFILE, and even any new code related to data saving, but the problem persists.

I know that with only this information, it is unlikely that anybody can tell me what is wrong, but would anybody have some advice what direction to look ? Would it make sense to think that a long string overwrite the value of some other variable ? How can it be possible ? Some guideline of clean C++ programming I might have broken ?

That some array is misbehaving sounds possible, and was the first thing I checked. I guess it should come from the arrays saving data, as they are the only new one. Thing is, even when I comment all the corresponding code, no change.

I try to give more information about my code. Here where I first use SAVEFILE (last argument of the runExperiment function)

int main(int argc, char *argv[])    {
  std::vector<Controller*> controllers;
  controllers.push_back(getConstrainedPDT(0,true));
  controllers.push_back(getConstrainedPDT(1,true));
  controllers.push_back(getConstrainedPDT(2,true));
  runExperiment(controllers,LENGTHS,WEIGHTS,RADIUS,ANGLEMIN,ANGLEMAX,MAXTORQUES,PUSHVECTOR,GRAVITY,RUNTIME,TIMESTEP,XTARGET,YTARGET,ITERATIONSAVEDATA,SAVEFILE);
  return 1;
}

and here the code of the function:

void runExperiment(std::vector<Controller*> controllers,const double * lengths, const double* weights, const double radius, const double* angleMin, const double* angleMax, const double* maxTorques,const double* pushVector,const dReal gravity,const dReal runTime,const dReal tstep,const dReal targetX,const dReal targetY,const int itSaveData,const std::string saveFile){

  endTime = runTime;
  simTime = 0.0;
  timeStep = tstep;

  dInitODE();
  world = dWorldCreate();
  space = dHashSpaceCreate(0);
  contactgroup = dJointGroupCreate(0);
  ground = dCreatePlane(space, 0, 0, 1, 0);
  dWorldSetGravity(world, 0, 0, gravity);

  createTargetObject(targetX,targetY);

  int nbData = static_cast<int>( ( endTime / timeStep ) / static_cast<double>(itSaveData) );

  robot = new R2DRobot(&world,controllers.size(),lengths,weights,radius,angleMin,angleMax,maxTorques,pushVector,controllers,itSaveData,nbData);

  dsFunctions   fn;
  fn.version = DS_VERSION;
  fn.start   = &setViewPoint;
  fn.step    = &loop;
  fn.stop = &stopSim;
  fn.path_to_textures = PATH_TO_TEXTURES;

  dsSimulationLoop(0, 0, 1280, 960, &fn);

 dWorldDestroy(world);
 dCloseODE();

 // NOTE: commenting the next three lines does not fix the problem !
 // it is the only place saveFile is used, except in the code of printData
 // I do not show the code of printData as commenting it does not change anything
 if (itSaveData>0){
    robot->printData(saveFile);
 }

 delete robot;

}

In the hope to find the unspecified variable (not that easy for a project with a lot of classes, some of them virtual), I played with the const parameters and observed the behavior of the robot. I reached a situation:

works fine all the time:

const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\tacit.txt";

crashes the program:

const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\ta";

Now the issue is, if I add a single line to the code of runExperiment (call to printf added):

printf("experiment.cpp - 1 \n");
robot = new R2DRobot(&world,controllers.size(),lengths,weights,radius,angleMin,angleMax,maxTorques,pushVector,controllers,itSaveData,nbData);

then both versions of SAVEFILE work fine and do give exactly similar results.

Now, if I delete the call to printf and add in the constructor of R2DRobot:

R2DRobot::R2DRobot(dWorldID * world, const int nbLinks, const double * lengths, const double * weights, const double radius,const double* angleMin,const double* angleMax,const double* maxTorques,const double* pushVector, std::vector<Controller*> controllers,int saveData,int nbData):
Robot(3*nbLinks+3,controllers),pushVector(pushVector),nbLinks(nbLinks),weights(weights),angleMin(angleMin),angleMax(angleMax),maxTorques(maxTorques),itSaveData(saveData){

printf("experiment.cpp - 1 \n");
// rest of the code

then the program crashes (if using the short version of SAVEFILE) but after printing "experiment.cpp -1" in the console.

Same thing if I move the call to printf to the constructor of Robot, the mother class of R2DRobot.

user4157124
  • 2,809
  • 13
  • 27
  • 42
Vince
  • 3,979
  • 10
  • 41
  • 69
  • The problem might be in your business logic. By using `std::string`, you are actually following good programming practice. If it runs out of memory then an exception will be thrown. But no bad overwriting occurs as you are doubting. – iammilind Apr 03 '13 at 07:00
  • Possibly an overrun writing to an array or buffer defined in a "nearby" variable. – Roger Rowland Apr 03 '13 at 07:00
  • 3
    To me this sounds like some _other_ part of the program reads from memory areas it shouldn't have access to. Perhaps you go out of bounds when reading from an array or something like that. Have you tried running your program in a tool that checks memory usage (e.g. valgrind)? – jogojapan Apr 03 '13 at 07:00
  • @iammilind : what would mean business logic ? – Vince Apr 03 '13 at 07:16
  • @roger_rowland : that was my first guess, but then how come these same array do not behave badly when the length of SAVEFILE is reduced ? This really confuses me. – Vince Apr 03 '13 at 07:18
  • @Vince, the actual code where you are using this `std::string`. I think you have posted the same now. – iammilind Apr 03 '13 at 07:19
  • @jogojapan: I should definitly look into this, I am using code::blocks and struggles with the tools. Tried to use the debugger and it just generate error messages all over the place .... – Vince Apr 03 '13 at 07:19
  • Can you show us the code of `R2DRobot::printData`? – Kiril Kirov Apr 03 '13 at 07:21
  • `getConstrainedPDT` is returning a pointer, and I see no obvious lifetime management of the pointed to resource. – Yakk - Adam Nevraumont Apr 03 '13 at 07:47

3 Answers3

8

This might be manifestation that your program does not initialize variables properly. When string was shorter, compiler created certain memory layout, and variables created on a stack (or on a heap) had certain values. By pure luck, those values were something that seemed to work right for you.

Now, since string has become longer, compiler has changed memory layout a little, and this led to slightly different layout. Now, these uninitialized variables might have slightly different values. It does not necessarily crash, but works differently.

mvp
  • 111,019
  • 13
  • 122
  • 148
  • 1
    Just to make sure I get it ... So my next step should be to check if I have uninitialized variables ? So something I declare but forgot to give a value to ? – Vince Apr 03 '13 at 07:30
  • Exactly. If you cannot find anything like that, then there must be *something* that changes your variables without you knowing. – mvp Apr 03 '13 at 07:35
  • For example, after declaration `dsFunctions fn;` you fill some fields of `fn`, but I am not convinced that you are filling *all* of them. In that case, they will remain uninitialized (contain junk) and this will pose a problem – mvp Apr 03 '13 at 07:43
  • indeed, one field was missing (command: http://opende.sourceforge.net/docs/structds_functions.html). Unluckily, correcting this did not solve the issue. – Vince Apr 03 '13 at 08:03
2

but would anybody have some advice what direction to look

This information is really not enough, unfortunately. Maybe, you can try using valgrind or a similar tool to analyze your code.


Would it make sense to think that a long string overwrite the value of some other variable? How can it be possible?

No, this is not a long string. It's not even close to long string. If the string is too long, you'll have an exception for invalid length.


Some guideline of clean C++ programming I might have broken

Not enough information. Using std::string is good and it's even recommended.

The problem is somewhere else. Sounds like undefined behavior to me.

Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187
1

The height number of arguments to runExperiment with are global variables are telling you that you may need a higher level object to wrap and organize it. While trying to write a constructor for such an object you will probably see and correct the problem with the incorrect/un-initialized variables, with will prevent undefined behavior.

qPCR4vir
  • 3,521
  • 1
  • 22
  • 32