潜在的指针问题和地址没有堆叠,malloc'd或(最近)免费

时间:2014-03-11 07:34:31

标签: c++ pointers valgrind

我在其中一个程序上遇到了分段错误而不确定原因。我跑了一个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++) {

}*/

这可能会发生什么?

2 个答案:

答案 0 :(得分:3)

main函数中,您声明了一个指向向量的指针,但是您永远不会将该指针实际指向任何位置。未初始化的局部变量具有不确定的值(并且它似乎是随机的),并且使用这些变量会导致未定义的行为


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

vector<PeekDeque<StringWrap>* > chains;

然后修改函数以获取参考:

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

事实上,在C ++中,你应该尽可能地避免指针,通常不需要它们。我实际上会敦促你不要在向量中存储指针。

答案 1 :(得分:1)

你的错误是根本的!

指针不是对象,chains只是将某个地址保存到某个内存中,该内存不是对象的地址,未分配且未初始化。

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

vector< PeekDeque < StringWrap > > 

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

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

ifstream* INFILEp = new ...是内存泄漏并且在没有delete INFILEp的情况下失败了 - 更好(再次):省略指针并使用ifstream INFILE(infileName.c_str());

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