Domanda

I am getting a segmentation fault on one of my programs and not sure why. I've ran a valgrind:

==7631== Memcheck, a memory error detector
==7631== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==7631== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==7631== Command: ./a.out wordsRMS.txt
==7631== Parent PID: 30431
==7631== 
==7631== Use of uninitialised value of size 8
==7631==    at 0x403C5C: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::begin() const (in /root/test/a.out)
==7631==    by 0x403D04: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::size() const (in /root/test/a.out)
==7631==    by 0x40328A: testNewWord(std::string const&, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >*) (in /root/test/a.out)
==7631==    by 0x4038FE: main (in /root/test/a.out)
==7631== 
==7631== Use of uninitialised value of size 8
==7631==    at 0x403C86: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::end() const (in /root/test/a.out)
==7631==    by 0x403D11: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::size() const (in /root/test/a.out)
==7631==    by 0x40328A: testNewWord(std::string const&, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >*) (in /root/test/a.out)
==7631==    by 0x4038FE: main (in /root/test/a.out)
==7631== 
==7631== Use of uninitialised value of size 8
==7631==    at 0x403C5C: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::begin() const (in /root/test/a.out)
==7631==    by 0x403D04: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::size() const (in /root/test/a.out)
==7631==    by 0x405E78: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::_M_range_check(unsigned long) const (in /root/test/a.out)
==7631==    by 0x405EAC: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::at(unsigned long) (in /root/test/a.out)
==7631==    by 0x402DD2: testNewWord(std::string const&, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >*) (in /root/test/a.out)
==7631==    by 0x4038FE: main (in /root/test/a.out)
==7631== 
==7631== Use of uninitialised value of size 8
==7631==    at 0x403C86: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::end() const (in /root/test/a.out)
==7631==    by 0x403D11: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::size() const (in /root/test/a.out)
==7631==    by 0x405E78: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::_M_range_check(unsigned long) const (in /root/test/a.out)
==7631==    by 0x405EAC: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::at(unsigned long) (in /root/test/a.out)
==7631==    by 0x402DD2: testNewWord(std::string const&, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >*) (in /root/test/a.out)
==7631==    by 0x4038FE: main (in /root/test/a.out)
==7631== 
==7631== Use of uninitialised value of size 8
==7631==    at 0x403D48: __gnu_cxx::__normal_iterator<PeekDeque<StringWrap>**, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> > >::__normal_iterator(PeekDeque<StringWrap>** const&) (in /root/test/a.out)
==7631==    by 0x403D6C: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::begin() (in /root/test/a.out)
==7631==    by 0x403DD2: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::operator[](unsigned long) (in /root/test/a.out)
==7631==    by 0x405EB9: std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >::at(unsigned long) (in /root/test/a.out)
==7631==    by 0x402DD2: testNewWord(std::string const&, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >*) (in /root/test/a.out)
==7631==    by 0x4038FE: main (in /root/test/a.out)
==7631== 
==7631== Invalid read of size 8
==7631==    at 0x402DD3: testNewWord(std::string const&, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >*) (in /root/test/a.out)
==7631==    by 0x4038FE: main (in /root/test/a.out)
==7631==  Address 0x6c894ce02464894c is not stack'd, malloc'd or (recently) free'd
==7631== 
==7631== 
==7631== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==7631==  General Protection Fault
==7631==    at 0x402DD3: testNewWord(std::string const&, std::vector<PeekDeque<StringWrap>*, std::allocator<PeekDeque<StringWrap>*> >*) (in /root/test/a.out)
==7631==    by 0x4038FE: main (in /root/test/a.out)
==7631== 
==7631== HEAP SUMMARY:
==7631==     in use at exit: 9,344 bytes in 5 blocks
==7631==   total heap usage: 5 allocs, 0 frees, 9,344 bytes allocated
==7631== 
==7631== 27 bytes in 1 blocks are possibly lost in loss record 1 of 5
==7631==    at 0x4A0695E: operator new(unsigned long) (vg_replace_malloc.c:220)
==7631==    by 0x33A9A9B860: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x33A9A9C23A: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x33A9A9CB44: std::string::reserve(unsigned long) (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x33A9A9CD5E: std::string::append(char const*, unsigned long) (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x33A9A76203: std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&) (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x40390B: main (in /root/test/a.out)
==7631== 
==7631== 37 bytes in 1 blocks are possibly lost in loss record 2 of 5
==7631==    at 0x4A0695E: operator new(unsigned long) (vg_replace_malloc.c:220)
==7631==    by 0x33A9A9B860: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x33A9A9C364: ??? (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x33A9A9C511: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.8)
==7631==    by 0x403873: main (in /root/test/a.out)
==7631== 
==7631== LEAK SUMMARY:
==7631==    definitely lost: 0 bytes in 0 blocks
==7631==    indirectly lost: 0 bytes in 0 blocks
==7631==      possibly lost: 64 bytes in 2 blocks
==7631==    still reachable: 9,280 bytes in 3 blocks
==7631==         suppressed: 0 bytes in 0 blocks
==7631== Reachable blocks (those to which a pointer was found) are not shown.
==7631== To see them, rerun with: --leak-check=full --show-reachable=yes
==7631== 
==7631== For counts of detected and suppressed errors, rerun with: -v
==7631== Use --track-origins=yes to see where uninitialised values come from
==7631== ERROR SUMMARY: 8 errors from 8 contexts (suppressed: 4 from 4)

The line that seems to be of importance:

Address 0x6c894ce02464894c is not stack'd, malloc'd or (recently) free'd

However, I'm not quite sure what to make of this. Here is my code:

/** Add word to new or existing chain.
 */
void testNewWord(const string& word, vector<PeekDeque<StringWrap>* >* chains) {
    bool foundChain = false;

    // check to see if we can add word into EXISTING chain
    for(std::vector<int>::size_type i = 0; i != chains->size(); i++) {
        // check front of chain
        if(ed1(StringWrap(word).str(), chains->at(i)->returnFront().str())) {
            //cout << "The word has an edit distance 1 with the front item." << endl;
            chains->at(i)->pushFront(StringWrap(word));
            foundChain = true;
            break;
        }

        // check rear of chain
        if(ed1(StringWrap(word).str(), chains->at(i)->returnRear().str())) { 
            //cout << "The word has an edit distance 1 with the rear item." << endl;
            chains->at(i)->pushRear(StringWrap(word));
            foundChain = true;
            break;
        } 

    }

    // otherwise create a NEW chain
    if(!foundChain) {
        PeekDeque<StringWrap>* newpd = new PeekDeque<StringWrap>(500);  

        newpd->pushFront(StringWrap(word));

        chains->push_back(newpd);
    }
}

int main(int argc, char* argv[]){   
    if(argc != 2){
        cerr << "Please specify a SINGLE .txt file to generate word chains from." << '\n' << "Usage: ./PeekClientRMS /path/to/file.txt" << '\n';
        return 1;
    }

    vector<PeekDeque<StringWrap>* >* chains;

    string word;

    string infileName = argv[1];
    ifstream* INFILEp = new ifstream(infileName.c_str(), ios_base::in);

    while ((*INFILEp) >> word) {
        testNewWord(word, chains);
    }

    INFILEp->close();


    /*for(std::vector<int>::size_type i = 0; i != chains->size(); i++) {

    }*/

}

Interestingly enough, when I uncomment the for loop at the bottom of main(), my program runs?

/*for(std::vector<int>::size_type i = 0; i != chains->size(); i++) {

}*/

What could be going on here?

È stato utile?

Soluzione

In the main function you declare a pointer to a vector, but you never make that pointer actually point anywhere. Uninitialized local variables have an indeterminate value (and it will seem to be random), and using those variables leads to undefined behavior.


In this case there's no need to use a pointer for the vector. Just declare it as a normal non-pointer variable, and pass it to the function as a reference.

Like

vector<PeekDeque<StringWrap>* > chains;

Then modify the function to take a reference:

void testNewWord(const string& word, vector<PeekDeque<StringWrap>* >& chains)

In fact, in C++ you should try to avoid pointers as much as possible, they are often not needed. I would actually urge you to not store pointers in the vector.

Altri suggerimenti

Your mistake is fundamental!

A pointer is no object, the chains is just holding an address to some memory, which is not the address of an object, not allocated and not initialized.

In C++ you should avoid needless allocations and prefer passing objects by value or reference:

vector< PeekDeque < StringWrap > > 

void testNewWord(const string& word, vector< PeekDeque< StringWrap> >& chains);

If you allocate via new you should pair up with delete, too (or delegate to a smart pointer).

The ifstream* INFILEp = new ... is a memory leak and defeats proper destruction without a delete INFILEp - better (again): omit the pointer and just use ifstream INFILE(infileName.c_str());

The PeekDeque<StringWrap>* newpd = new PeekDeque is likely a memory leak, too.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top