如何解释GDB回溯以确定分段错误?

How to interpret a GDB backtrace in order to determine a segmentation fault?

本文关键字:分段 错误 回溯 GDB 何解释 解释      更新时间:2023-10-16

我正在上入门级编程课。我知道分段错误是由于内存存储中的错误造成的。我编写的程序应该获取一个提供给我们的文件,该文件是代码,其中包含解码它的说明,然后打印解码的消息。

我们有几个测试用例,我的代码为其中一些运行,但不适用于最后一个。我今天第一次了解了用于调试的 GDB,并使用回溯完整来尝试查找错误,但我不完全确定如何解释它给我的内容。

这是我编写的代码。 **编辑的代码输出

当我回溯时,这就是它告诉我的。

#2  0x0000000000401523 in main () at main.cpp:42
second = 61 '='
third = 72 'H'
msg = 0x606308
i = 8
chars = ""
first = 90 'Z'
numMess = 8
out = <incomplete type>
name = "input4.txt"
in = <incomplete type>
arr = "IJKLMNOPQRSTUVWXYZABCDEFGH"

我不知道回溯告诉我什么,我不确定如何处理这些信息来发现和修复我的错误。

来自跟踪的提示是

i = 8
chars = ""
numMess = 8

i等于numMesschars为空。

为什么这很重要?查看numMess的来源,我们看到它用于调整msg指向的动态数组的大小,msg稍后按i进行索引。当i等于numMess时,msg[i]是越界的。

那么这是怎么发生的呢?

string chars;
getline(in, chars); // this doesn't make much sense. Reconsider it
for (chars; std::getline(in, chars); i < numMess) {

这就是出错的地方。for 循环应该看起来像

for (initializer ; exit condition ; iterator to advance the loop)

for (chars; // does nothing. Compiler may be warning you
std::getline(in, chars); // loop exits on failed read
i < numMess) { // does nothing to advance the loop

此处没有任何内容可以阻止i超过numMessi < numMess因为它没有被用作退出条件。对,但是为什么std::getline(in, chars);在到达文件末尾时不踢出循环?文件末尾的空行。 已成功将chars设置为空字符串。

for ( ; // nothing happening here
i < numMess and std::getline(in, chars) ;
++i) { // and remove the ++i from the end of the loop.

让你摆脱目前的困境,并可能给你一个做你想做的事的程序。还没有测试过。

但是,如果文件中有错误并且文件在到达numMess之前退出怎么办?这就是保罗·麦肯齐(PaulMckenzie)正在做的事情。你最好根本不相信numMess,而选择更像的东西

int numMess = 0;
in >> numMess; // not that we care
vector<Messages> msg;
//read file
int i = 0;
string chars;
while (std::getline(in, chars)) { // get each line. Note this gets the empty line, too
Messages temp; // make a temporary for storage
temp.messageNum = i + 1;
temp.codedMessage = chars;

//decode file
for (char &j : chars) {
if (j - 'A' >= 0 && j - 'A' < 26)
j = arr[j - 'A'];
}
temp.decodedMessage = chars;
msg.push_back(temp);
}