我在我的一个程序上得到一个分段错误,不知道为什么。我已经运行了一个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
也可能是内存泄漏