【问题标题】:Segmentation fault on one Linux machine but not another with C++ code一台 Linux 机器上的分段错误,而另一台使用 C++ 代码的机器上没有
【发布时间】:2015-05-15 17:16:34
【问题描述】:

我遇到了一个特殊的问题。我在工作中的 Linux 集群上开发了一个 C++ 程序。我曾尝试在 Ubuntu 14.04 机器上使用它,但该程序由 6 个文件组成:main.hpp、main.cpp(依赖于)sarsa.hpp、sarsa.cpp(Sarsa 类)(依赖于) wec.hpp,wec.cpp 确实可以编译,但是当我运行它时,它要么返回segmenation fault,要么不输入Sarsa 类的一个基本函数。

主要代码调用构造函数和setter函数没有问题:

  Sarsa run;
  run.setVectorSize(memory,3,tilings,1000);

等等

但是,它不能运行公共函数 episode ,因为应该包含一个大整数的 learningRate 对于所有情节(迭代)都返回 0。

learningRate[episode]=run.episode(numSteps,graph);}

我尝试用gdb调试代码,结果返回:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000408f4a in main () at main.cpp:152
152     learningRate[episode]=run.episode(numSteps,graph);}

我也试过valgrind,返回:

==10321==  Uninitialised value was created by a stack allocation
==10321==    at 0x408CAD: main (main.cpp:112)

但没有内存泄漏问题。

我想知道是否有尝试调试外部文件sarsa.cpp 的设置,因为我认为该类可能是罪魁祸首

在文件中,我使用 C++v11 语言(不过我会在编译时遇到错误),所以我什至使用 g++ -std=c++0x 进行编译,但没有任何改进。

不幸的是,由于代码的大小,我无法在此处发布。我真的很感激这个问题的任何帮助。我错过了什么明显的东西吗?你能帮我调试一下吗?

提前感谢您的帮助。

更正: main.cpp:

全局数组的定义: `#define numEpisodes 10

int learningRate[numEpisodes];`

main 函数即将结束:

for (int episode; episode<numEpisodes; episode++) { if (episode==(numEpisodes-1)) { // Save the simulation data only at the graph=true;} // last episode learningRate[episode]=run.episode(numSteps,graph);}

【问题讨论】:

  • 1.由于段错误发生在派生自main.cpp 的代码中,这似乎是一个更好的起点。 main.cpp:152 段错误的最可能原因是learningRate 是一个未初始化的指针(注意 Valgrind 的警告)或epsiode 不是learningRate 引用的静态或动态数组的有效索引。
  • 2.在多个文件之间拆分源代码不会对gdb 或大多数其他调试器带来任何特殊或不寻常的挑战。调试从多个来源构建的程序 Just Works。如果调试器可以找到main.cpp(它可以)并且您没有更改其他源的相对位置,那么它也会找到其他源。
  • 在我的问题结束时,我添加了main.cpp 的部分,其中可以找到learningRate。我不明白为什么learningRate 应该是一个未初始化的指针
  • 反问:给定for (int episode; episode&lt;numEpisodes; episode++),循环体第一次迭代开始时episode的值是多少?
  • 非常感谢!我简直不敢相信我在这上面浪费了几个小时,试图在课堂上寻找错误,而我根本没有初始化情节。

标签: c++ linux segmentation-fault portability


【解决方案1】:

正如您刚刚添加到问题中的代码所揭示的那样,问题的出现是因为您没有初始化 episode 变量。在赋值之前使用其值的任何代码的行为都是未定义的,因此程序在一种环境中的行为与在另一种环境中的行为不同是完全合理的。

【讨论】:

    【解决方案2】:

    分段错误表示无效的内存访问。通常这意味着在某个地方,您正在读取或写入超出数组的末尾,或通过无效指针,或通过已被释放的对象。您不一定会在错误发生的地方遇到分段错误;例如,您可以将数组末尾的内容写入堆元数据,这会在您稍后尝试分配或释放不相关的对象时导致崩溃。因此,程序看起来在一个系统上运行但在另一个系统上崩溃是完全合理的。

    在这种情况下,我将从查看learningRate[episode] 开始。 episode 的值是多少?是否在learningRate的范围内?

    【讨论】:

      【解决方案3】:

      我想知道是否有尝试调试外部文件sarsa.cpp 的设置,因为我认为该类可能是罪魁祸首

      It's possible to set breakpoints in functions other than main.cpp.

      打破位置

      在给定的位置设置断点,可以指定函数名、行号或指令地址。

      至少,我认为这是你的问题。 You'll also need to know how to step into functions.

      更重要的是,您需要了解您的工具试图告诉您什么。段错误是操作系统对尝试取消引用不属于您的内存的反应。一个常见的原因是试图取消引用NULL。另一个将尝试取消引用从未初始化的指针。 Valgrind 错误消息表明您可能有一个未初始化的指针。

      如果没有代码,我无法告诉您为什么当您在家庭系统上运行程序时指针没有被初始化,但是当您在工作中运行它时(显然)被初始化了。我怀疑您的家庭系统上没有必要的数据,但您需要进行调查并弄清楚这一点。不断问自己的基本问题是“我的家用电脑和我的工作电脑有什么不同?”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 2015-11-08
        • 1970-01-01
        • 2015-06-29
        • 2012-09-29
        • 1970-01-01
        • 2021-12-29
        相关资源
        最近更新 更多