首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++字符串和内存管理

C++字符串和内存管理
EN

Stack Overflow用户
提问于 2013-04-03 14:56:26
回答 3查看 380关注 0票数 1

我现在正在做一个相当复杂的项目,涉及到一个模拟机械臂的控制。我完成了这个项目的第一个版本,它工作得很好。我只是添加了一些新代码,这些代码在每次迭代时收集有关系统的一些信息,将其保存在一些数组中,最后将所有内容打印到一个文件中,供以后分析。

现在,一些真正奇怪的事情正在发生。如果我定义保存数据的文件,如下所示:

代码语言:javascript
复制
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\ta";

一切都很好,和我添加新代码之前完全一样(加上保存数据)。

但如果我这样定义它:

代码语言:javascript
复制
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\tacit.txt";

然后系统以另一种方式运行。不会崩溃,但机械臂的移动方式不同。

我试图注释所有使用SAVEFILE的代码,甚至任何与数据保存相关的新代码,但问题仍然存在。

我知道,只有这些信息,不太可能有人能告诉我哪里出了问题,但有没有人能给出一些建议,应该往哪个方向看呢?认为一个长字符串覆盖其他变量的值有意义吗?这怎么可能呢?我可能破坏了一些干净的C++编程准则?

一些数组听起来可能行为不端,这是我检查的第一件事。我猜它应该来自保存数据的数组,因为它们是唯一的新数组。问题是,即使我注释了所有相应的代码,也没有变化。

我试着给出更多关于我的代码的信息。在这里我第一次使用了SAVEFILE ( runExperiment函数的最后一个参数)

代码语言:javascript
复制
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;
}

下面是函数的代码:

代码语言:javascript
复制
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;

}

为了找到未指定的变量(对于一个有很多类的项目来说,这并不容易,其中一些是虚拟的),我使用const参数并观察了机器人的行为。我遇到了这样的情况:

一直都运行得很好:

代码语言:javascript
复制
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\tacit.txt";

使程序崩溃:

代码语言:javascript
复制
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\ta";

现在的问题是,如果我在runExperiment的代码中添加一行(添加了对printf的调用):

代码语言:javascript
复制
printf("experiment.cpp - 1 \n");
robot = new R2DRobot(&world,controllers.size(),lengths,weights,radius,angleMin,angleMax,maxTorques,pushVector,controllers,itSaveData,nbData);

那么两个版本的SAVEFILE都可以很好地工作,并给出完全相同的结果。

现在,如果我删除对printf的调用并添加R2DRobot的构造函数:

代码语言:javascript
复制
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

然后程序崩溃(如果使用的是SAVEFILE的短版本),但在控制台中打印"experiment.cpp -1“之后。

如果我将对printf的调用移到Robot的构造函数,也是如此,Robot是R2DRobot的母类。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-03 15:01:18

这可能是你的程序没有正确初始化变量的表现。当字符串较短时,编译器会创建特定的内存布局,并且在堆栈(或堆)上创建的变量具有特定值。幸运的是,这些价值观似乎对你来说是正确的。

现在,由于字符串变得更长,编译器稍微改变了内存布局,这导致了略微不同的布局。现在,这些未初始化的变量可能具有略微不同的值。它不一定会崩溃,但工作方式不同。

票数 8
EN

Stack Overflow用户

发布于 2013-04-03 15:01:07

,但是谁能给我一些建议,应该往哪个方向看呢

不幸的是,这些信息确实不够。也许,您可以尝试使用valgrind或类似的工具来分析代码。

认为一个长字符串覆盖了其他变量的值,这有意义吗?这怎么可能呢?

不,这不是一个很长的字符串。它甚至不是很长的弦。如果字符串太长,则会出现长度无效的异常。

一些干净的C++编程指南,我可能已经破坏了

信息不足。使用std::string是很好的,甚至是推荐的。

问题出在别的地方。对我来说,这听起来像是未定义的行为。

票数 2
EN

Stack Overflow用户

发布于 2013-04-03 15:51:09

使用全局变量的runExperiment参数的高度告诉您,您可能需要一个更高级别的对象来包装和组织它。在尝试为这样的对象编写构造函数时,您可能会看到并纠正错误的/未初始化的变量的问题,这将防止未定义的行为。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15780757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档