为什么在VS 2010 C++中,我的程序在调试器中运行良好时会崩溃,但在没有调试器的情况下运行时会崩溃



所以我正在为一个大学班级编写一个图形程序。老师有代码,但她有EXE。代码有效。如果我在visual studio中,开始调试代码,它会很好地工作。该程序通过std::cout将指令打印到控制台,然后出现opengl窗口,一切都按预期进行。然而,如果我在没有调试的情况下点击ctrl+f5进行运行,则会打印出指令并显示窗口,但窗口的内容只是纯白的。大约一分钟后,程序崩溃,窗口弹出一条消息,说对不起程序崩溃或类似的话。

如果我进入项目文件夹,进入调试文件夹并单击.exe,说明会再次打印出来,然后弹出一个窗口,说"调试断言失败",并将其归咎于矢量索引超出范围。这将是因为,除了为什么当我通过visualstudio在调试模式下运行程序时不会发生这种情况?

如果我在visual studio中,将配置从调试更改为发布,则会再次打印指令,这一次会弹出一个消息,说内存分配不好。它指向这行代码:

Model* mutiplyMatrix(Model model,CMatrix matrix)
{
    Model* m=new Model();
    for(unsigned int i=0;i<model.vectorList.size();i++)
    {
        CVector* v=new CVector();
        v->m=matrix*(*(model.vectorList.at(i)->m));
        v->drawBit=model.vectorList.at(i)->drawBit;
        m->addVectorToList(v);
    }
    return m;
}

确切的线路是

CVector* v=new CVector();

所以我的问题是如何得到一个可以交给老师的exe。我很乐意包括所需的图书馆等。问题是,这个程序可以工作,但只有当我在调试模式下从visualstudio执行它时。在发布模式下使用或未进行调试时,程序会崩溃。

这是视觉工作室2010。

听起来很像您正在使用一个未初始化的变量,它会影响循环的执行次数。在调试模式下,该值可能会一直设置为低值或0,这只是由于在调试器下运行的性质。然而,当不在调试器下运行时,您可能会得到一个非常大的值,这反过来会导致上面的迭代运行很长一段时间,然后在内存不足时崩溃。我会从model.vectorList.size()向后跟踪,看看值是从哪里来的。在您进入打印大小的for循环之前,我还会添加一行cout

编辑:

好吧,我仍然认为你的问题与一个未初始化变量的无限内存分配有关,但你在代码中做的很多事情阻碍了

Model* mutiplyMatrix(Model mode,CMatrix matrix)

这将触发Model和CMatrix的副本。如果复制构造函数或析构函数的设计不正确,那将是有问题的,尤其是在大量使用原始指针成员的情况下。考虑以下类别:

class Foo {
  char * data;
  Foo() { 
    data = new char[1024];
  }
  virtual ~Foo() {
    delete[] data;
  }
};

看起来不错吧?我分配内存并释放它。但是如果我有一个函数会发生什么

void bar(Foo foo) {
  std::cout << "Called bar" << std::endl;
}

如果我用我的一个foo对象调用那个函数,我就破坏了内存。bar()接受一个Foo对象,而不是Foo引用,所以我的原始Foo在交给bar()之前只是被复制了一下。因为我没有定义复制构造函数,所以会调用默认的复制构造函数,这意味着指针值只是被复制的。这意味着当bar()结束时,指针将被类上的~Foo()析构函数释放。但稍后,当我的原始Foo实例离开作用域时,相同的指针将再次被删除。内存损坏和崩溃。

至少你的方法应该声明为

Model* mutiplyMatrix(Model & mode,CMatrix & matrix)

或优选

Model* mutiplyMatrix(const Model & mode,const CMatrix & matrix)

更糟糕的是,因为我们可以从下面的源代码中推断出Model有一个成员,看起来像这样:

std:list<CVector*> vectorList;

当您的传入模型被复制然后销毁时,它可能会把堆弄得一团糟。

我最大的建议是停止使用这么多该死的指针。

最新更新