JKostikiadis
JKostikiadis

Reputation: 2917

C++ corrupted double-linked list

I am new in c++ coming from Java and I am facing a problem with c++ I/O. I have made a small program to illustrate me problem. The main idea is to have 3-dimensional array and initialize it's values by reading a text file with specific text format. The file contains the number of Levels (L) which is the first dimension and the size of rows and columns (N) which is the second and the third dimensions ( array[L][N][N] ).

Edit : to execute my program i use g++ -std=c++0x program.cpp

Here is the program :

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int num_of_stages;
int N ;
string ***stages;

void readFile(string file_name){
    string line;
    int pos;

    ifstream file (file_name);

    if (file.is_open()){

        getline (file,line);                    // L=XXX
        pos = line.find("=");
        line = line.substr(pos+1);
        num_of_stages = atoi(line.c_str());
        cout << "L=" << num_of_stages << endl;

        getline (file,line);                    // N=XXX
        pos = line.find("=");
        line = line.substr(pos+1);
        N = atoi(line.c_str());
        cout << "N=" << N << endl;      

        // setting the stages array with dimensions stages[L][N][N]
        stages = new string**[num_of_stages];
        for(int i = 0 ; i < N ; i ++){
            stages[i] = new string*[N];
            for(int j = 0 ; j < N ; j++){
                stages[i][j] = new string[N];
            }
        }

        for(int i = 0 ; i < num_of_stages ; i++){
            getline (file,line);                // Level comment
            cout << "Level " << line << endl; 
            for(int j = 0 ; j < N ; j++){
                for(int k = 0 ; k < N ; k++){
                    string currentValue ;
                    file >> currentValue;
                    stages[i][j][k] = currentValue;
                    cout << currentValue << " " ;
                }
                cout << endl;
            }
            cout << endl << endl;
            // I am guessing that this getLine() 
            // is necessary to read the end of the line
            // if I try remove it everything goes wrong
            // everytime I print the line's values is ' ' (empty)
            getline (file,line);
            // remove any string value to detect end of file        
            // so the if statement below will be true
            line.clear();
        }
        getline (file,line);                    // END OF MAZE comment
        cout << line << endl;
        if(line != "END OF MAZE"){
            cout << "Wrong file format" << endl;
            file.close();
            exit(0);
        }
        file.close();
    }else{
        cout << "Missing file with name : " << file_name << endl;
        exit(0);
    }
    // program never reach that point
    cout << "Bla bla bla" << endl;
}

int main(){
    readFile("file1.maz");
    return 0;
}

My File has this text format :

L=5
N=16
LEVEL 1
T2 T3 T1 T2 E E T1 E E T2 T2 T1 T2 T1 T2 T1 
T1 T1 T2 T1 T2 T3 T2 T3 T2 T2 T3 T3 T1 E T3 T1 
T2 E T1 T1 T3 T2 T1 T3 E T3 T3 E T1 E T1 T1 
T1 T3 T2 E T1 T1 T2 E T2 T2 T2 T1 T3 T3 T1 T3 
E E T1 T3 T1 T3 T1 T2 T2 T1 T1 E T2 T1 T1 T3 
T2 T1 T1 T3 T3 E T2 T3 T3 T2 T1 E T3 T2 T1 T2 
T2 T1 T3 T2 T2 E T2 E E E T3 T3 T2 T3 T3 T1 
E E E T2 E E T3 E T1 T2 T1 T2 T1 T3 T3 E 
T3 T2 T1 T3 E T1 E T2 T3 T1 T2 T2 T3 T2 E T1 
T2 T3 E E T2 T2 E T3 E E T3 T1 T3 T1 E T3 
T1 T1 E T1 T1 T3 T3 T1 E T2 T3 T1 T3 T3 T3 E 
T3 T1 T1 T1 T2 T2 T3 T1 T3 T2 E T2 T1 E T1 E 
T3 E T2 E T1 T1 T3 T2 T3 T2 T3 E T3 T3 T2 T2 
T1 T1 E T3 T1 E T2 T1 T3 T1 T1 T2 T2 T2 T1 T2 
T3 E T3 T3 T3 T2 T1 T1 E E E T2 T1 T2 E T3 
T1 E T3 T2 E E T3 E E E T3 T1 E T2 T2 E 
LEVEL 2
T2 T2 T3 T2 T1 T1 T3 T3 T1 E T1 T2 T3 T2 E T1 
T1 T3 T2 E T2 E T2 T2 T3 T1 T3 T1 E T3 T3 T3 
T3 T3 T3 E T3 T3 E T3 T1 T1 T1 T2 T2 T3 T2 T1 
T2 T3 T1 T2 T1 E E T2 T1 T1 T3 T2 E T1 T2 T3 
T2 T2 T3 E T3 T3 T1 T1 E T3 T3 T2 T3 E T1 E 
T2 T3 T3 T2 E E E T2 T1 T3 E T2 T1 T3 E T1 
T3 T3 E T1 E T3 T1 T1 T3 T3 E T3 E T3 T1 T2 
T2 E T1 E T1 T3 T1 T3 E T3 T1 E T1 T3 T1 E 
T3 E E T1 T3 T2 T2 E T3 T2 T2 T1 E T1 T2 T2 
T3 T3 E E T2 T1 T3 T1 E T3 E E E E T1 E 
T3 E E T2 E E T2 T1 T2 T1 T1 T2 T3 T2 T3 T1 
T3 E T2 T3 T1 T3 T3 T2 E T1 T2 T2 T2 T2 T1 E 
T2 T3 T1 T3 T2 T3 T2 T3 T1 T1 T3 T3 T2 T2 E T3 
T3 T3 T2 T3 T1 T3 T1 T1 T2 E E T3 E T1 T2 T2 
T1 T2 T2 T2 T1 T1 T1 E T1 T2 T2 E T1 T3 T1 T3 
E T2 E E T3 T3 E T1 T1 T2 E T1 T3 E T3 T3 
LEVEL 3
T3 E T1 T3 T3 T3 T2 T3 T1 E T1 T1 T1 T2 E T1 
T1 E E T2 T1 T3 T1 E T1 T3 T3 T3 T3 T2 T1 T1 
T2 T3 T1 T2 T3 E T3 T1 T3 E T1 T3 T1 T2 E T3 
T1 T2 T1 E T2 T1 T1 T3 T2 T2 T2 T2 T3 T3 E T1 
T3 T2 T3 E T3 T1 T1 T2 E T2 E T3 T1 T1 E T1 
T3 E T2 T3 T2 E E T2 T1 E T1 E T2 E T3 T3 
E T2 T1 T3 E T1 E E T3 T1 T1 T3 T2 T1 E E 
T1 T3 T2 T3 T1 T2 T1 E T2 T3 T3 T1 T3 T2 T3 T2 
E T2 T1 T1 E T1 T2 T3 E T2 T1 T3 E T3 E T2 
T3 E T1 T3 T2 E T1 T1 E T2 T3 T3 T3 T2 E E 
T2 E E T2 T3 T3 T1 T2 T1 T2 T1 T3 T2 T2 T2 T2 
T1 E T2 T3 T2 E T2 T2 T1 T2 T1 E T2 E T2 T3 
T2 E T1 E E T1 T3 T1 E T1 E T1 T1 E T2 T2 
T2 T3 T3 T1 E T1 T1 E T1 T3 T3 T3 E T2 T2 E 
T2 T1 T1 T1 T2 E T1 T3 T3 T3 T2 E T3 E T2 E 
E T2 T1 T2 E T1 T3 T1 T3 T1 T3 T2 T1 T1 E T3 
LEVEL 4
E E E T1 T2 T1 T1 E T1 T3 T2 E E T1 T3 T2 
T2 T2 E T3 T3 E E T1 T3 E E T1 T2 T3 T2 E 
T2 T3 T3 T3 T3 E T2 T2 T1 T1 T1 T2 T3 E T2 T1 
T2 T1 E T2 T3 T3 T3 E T1 T3 T2 T2 T2 T1 E T3 
T3 T2 T3 E T2 E T2 E T2 T1 T1 T3 E T2 E T2 
E T1 T1 T1 E E E T2 T1 T1 T3 T1 T2 E T3 T3 
E T3 E T1 E T2 T2 T1 T2 E T3 T3 T3 T1 T3 T3 
E T2 T1 T1 T2 T2 T3 E E T1 T3 T3 T3 T1 T2 E 
T3 T3 T2 E T3 T2 E T1 T2 E E T2 T2 T1 E E 
T3 E E T2 T3 T2 T1 T2 T3 T1 E T1 T3 T2 T1 T2 
E T2 T1 T2 T3 T2 E T3 T3 T1 E T3 T3 T3 T3 T1 
E T2 T1 T1 T1 T3 E T2 E T3 T1 T1 T2 T2 E E 
T3 T3 T3 T2 E T1 T1 T3 T3 T3 E T3 T3 T3 T1 T1 
T2 T1 T1 T2 E E E T3 T1 T3 T3 T1 E E T1 T2 
T1 T2 T2 E T2 T1 T3 T3 T1 T1 T2 T3 T3 T1 T2 T1 
T1 T2 T1 E T1 T3 T2 T1 T1 T2 E E T1 E T3 T1 
LEVEL 5
T1 T1 T3 T1 T2 T3 E T2 T2 T1 T3 T2 T2 E T1 T1 
T3 E T3 E T2 T1 T1 T3 T2 T3 T1 T1 T3 T2 T3 T1 
T2 T3 T1 T2 T2 E T1 T3 E T2 T2 T2 T3 T3 T2 T2 
T1 E T1 T1 T2 T1 T3 E T3 E T1 T1 T3 T3 T1 T3 
T1 T1 T3 T2 T2 E E E E T2 E T1 T1 T2 E T2 
E T2 E E T3 E T1 E E T1 T3 T2 E E T2 E 
T2 T3 T3 E T3 T2 T2 T3 T1 E E E T3 T2 T3 T2 
T1 T1 T1 T1 E T2 E E T1 T3 T2 T1 T3 E E E 
T1 T1 E T1 T3 E E E T1 T1 T1 T3 T1 T2 T3 T3 
T2 T2 T3 T3 E T2 T1 T3 T2 T1 T3 T1 T1 T2 T3 E 
T3 T1 T3 T3 T3 E T1 T1 E T3 T2 E T2 T2 E T1 
T1 T3 E T1 T2 T2 T2 T2 T3 T3 E E T3 T1 T1 T2 
T1 E E T3 T2 T2 T1 T2 T2 T2 T2 T1 T3 T3 T3 E 
T3 E E T2 T1 T3 T1 T2 E E T3 E T3 T2 T1 E 
T1 T3 T1 T3 T2 E E T2 T2 T2 E T1 T2 E T1 T1 
T2 T3 T1 T3 T1 T1 T2 T2 E T1 T2 T1 T2 E E T1 
END OF MAZE

When I execute my program with the above file example I am getting this error :

Error in `./a.out': corrupted double-linked list: 0x0000000001174280 ***

Here is the gdb backtrace:

(gdb) backtrace
#0  0x00007ffff7531cc9 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff75350d8 in __GI_abort () at abort.c:89
#2  0x00007ffff756e394 in __libc_message (do_abort=do_abort@entry=1, 
    fmt=fmt@entry=0x7ffff767cb28 "*** Error in `%s': %s: 0x%s ***\n")
    at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007ffff75790f7 in malloc_printerr (action=<optimized out>, 
    str=0x7ffff7678bfc "corrupted double-linked list", ptr=<optimized out>)
    at malloc.c:4996
#4  0x00007ffff757a7a7 in _int_free (av=0x7ffff78b9760 <main_arena>, p=<optimized out>, 
    have_lock=0) at malloc.c:3996
#5  0x00007ffff7b898be in std::basic_filebuf<char, std::char_traits<char> >::_M_destroy_internal_buffer() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff7b89d47 in std::basic_filebuf<char, std::char_traits<char> >::close() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff7b8b3ad in std::basic_ifstream<char, std::char_traits<char> >::close() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8  0x00000000004018b9 in readFile(std::string) ()
#9  0x0000000000401a3d in main ()

I have see other post about this current of problem and some of them was about getting out of array indexes but I have test everything and I am always inside bounds. So is something wrong about the way I am reading the file?. I hope this is not a silly question. Thanks in advance.

Upvotes: 0

Views: 8090

Answers (1)

Kevin
Kevin

Reputation: 7324

You are going out of bounds:

stages = new string**[num_of_stages];
    for(int i = 0 ; i < N ; i ++) {
        stages[i] = new string*[N];

If num_of_stages < N you are accessing past the array.

You should use a std::vector instead of dealing with raw pointers and using new/delete yourself. It has an at function that does bounds checking.

Upvotes: 4

Related Questions