简体   繁体   中英

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

I am in an entry level programming class. I understand that segmentation faults are due to an error in memory storage somewhere along the way. The program I wrote is supposed to take a file given to us that is in code and contains the instructions to decode it and then print the decoded message.

We have several test cases and my code runs for some of them, but not for the last one. I learned about GDB for debugging for the first time today and used backtrace full to try and source the error, but I'm not totally sure how to interpret what it gave me.

This is the code that I wrote. **edited code out

When I did a backtrace, this is what it told me.

   #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 don't know what the backtrace is telling me and I'm unsure of what to do with that information to discover and fix my error.

The hints from the trace are

i = 8
chars = ""
numMess = 8

i equals numMess and chars is empty.

Why does this matter? Looking at where numMess comes from, we see it's used to size the dynamic array pointed at by msg and msg is later indexed by i . when i equals numMess , msg[i] is out of bounds.

So how did this happen?

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

Here's where things went wrong. A for loop should look something like

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

but

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

Nothing in here prevents i from exceeding numMess because i < numMess is not being used as an exit condition. Right, but why doesn't std::getline(in, chars); kick out of the loop when it hits the end of the file? Empty line at the end of the file. chars was successfully set to an empty string.

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

Gets you out of the current predicament and might give you a program that does what you want. Haven't tested it.

But what if there is a mistake in the file and the file exits before reaching numMess ? This is the sort of stuff PaulMckenzie is getting at. You're better off not trusting numMess at all and going with something more like

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM