潜在的指针问题和地址未堆叠、错误或(最近)释放



我在我的一个程序上得到一个分段错误,不知道为什么。我已经运行了一个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)

似乎很重要的那一行:

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

然而,我不太确定这是怎么回事。下面是我的代码:

/** 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++) {
    }*/
}

有趣的是,当我取消注释main()底部的for循环时,我的程序运行?

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

这里可能发生了什么?

main函数中,您声明了一个指向向量的指针,但您从未使该指针实际上指向任何地方。未初始化的局部变量具有不确定的值(并且看起来是随机的),使用这些变量会导致未定义行为


在这种情况下,不需要为vector使用指针。只需将其声明为普通的非指针变量,并将其作为引用传递给函数。

vector<PeekDeque<StringWrap>* > chains;

然后修改函数以接受引用:

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

实际上,在c++中应该尽量避免使用指针,它们通常是不需要的。我强烈建议大家不要在vector容器中存储指针

你的错误是根本性的!

指针不是对象,chains只是保存一些内存的地址,这不是对象的地址,没有分配也没有初始化。

在c++中,你应该避免不必要的分配,更喜欢通过值或引用传递对象:

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

如果你通过new分配,你也应该与delete配对(或者委托给智能指针)。

ifstream* INFILEp = new ...是一个内存泄漏,如果没有delete INFILEp就会失败-更好的(再次):省略指针,只使用ifstream INFILE(infileName.c_str());

PeekDeque<StringWrap>* newpd = new PeekDeque也可能是内存泄漏

相关内容

最新更新