2011-11-29 78 views
1

我的代碼的這一部分(對於this project)給了我一個分段錯誤。源代碼可用here在C++中迭代std :: set <std::string>時出現分段錯誤

void PackageManager::install_package(string pname) 
{ 
    if(repository->exists_package(pname)) { 
    Package *pkg; 
    ConcretePackage *cpkg; 
    MetaPackage *mpkg; 
    if(repository->is_virtual(pname)) { 
     //code for dealing with meta packages 
     mpkg = new MetaPackage(pname); 
     pkg = mpkg; 
     system->operator+(pname); 
    } else { 
     //code for dealing with concrete packages 
     cpkg = new ConcretePackage(pname); 
     pkg = cpkg; 
     system->operator+(pname); 
     if(cpkg->getDependencies().size() > 0) { 
     for(set<string>::iterator sit = pkg->getDependencies().begin(); 
      sit!=pkg->getDependencies().end(); ++sit) { 
      cout<<*sit<<endl; 
      system->operator+(*sit); 
     } 
     } 
    } 
    } else { 
    cout<<"Invalid Package Name"<<endl; 
    } 
} 

這是我運行gdb和回溯時的錯誤。

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7b6db03 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)() 
    from /usr/lib/libstdc++.so.6 
(gdb) backtrace 
#0 0x00007ffff7b6db03 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)() 
    from /usr/lib/libstdc++.so.6 
#1 0x00000000004052e8 in PackageManager::install_package (this=0x7fffffffe280, pname=...) at packagemanager.cpp:39 
#2 0x000000000040575a in main() at packagemanager.cpp:79 

我想遍歷一組並執行一些操作。如果需要,我可以推送更多的代碼。 如果有人能指導我到一個能夠學會理解這些段錯誤的地方,我還會喜歡它。我對他們瞭解不多,當我遇到這些時我傾向於恐慌。

這是System類的operator +。

void System::operator+(string pname) 
{ 
    installed_packages.insert(pname); 
    log.push_back("Added " + pname); 
} 

我知道這個設計是不是最好的,但我想實現一個清單的這個項目,它涵蓋面向對象編程的各個領域的項目。該清單也可在github上獲得。

我試圖通過調試器運行代碼,printng out * sit。它有一段時間,然後崩潰。我不太瞭解gdb。

+2

什麼是'system-> operator +()'? – Drahakar

+1

@GregHewgill從我在堆棧跟蹤中可以看到的錯誤來自'Packaged :: :: install_package'在'std :: ostream'的'operator <<'中。看起來像是在for循環中。 – Drahakar

+0

@GregHewgill:我在github上添加了我的回購鏈接。 – nikhil

回答

5

StackOverflow有幾個「什麼是分段錯誤?」風格Q &答:

What is a segmentation fault?

理想情況下,你在一個環境中調試並逐步執行代碼行由行,或放置斷點的能力的工作。這可以幫助您隔離您的崩潰情況。你已經有了在堆棧跟蹤行號 - 其中我們假設點吸菸槍:

cout<<*sit<<endl; 

但隨着調試器步進通過能回答喜歡,這是否通過循環發生在第一時間問題..如果不是,那麼在哪個元素上。


UPDATE:看看這個代碼,你必須在GitHub上(不包括上面的代碼)的作品,我看到ConcretePackage::getDependencies()由值返回一組並通過引用不。這意味着每次你給成員打電話時,你都會得到一套新的副本。來自不同容器的迭代器不應該相互比較,即使是同一類型:

comparing iterators from different containers

爲了解決這個問題,你可以改變:

for(set<string>::iterator sit = pkg->getDependencies().begin(); 
     sit!=pkg->getDependencies().end(); ++sit) { ... } 

...到:

set<string> deps = pkg->getDependencies(); 
for(set<string>::iterator sit = deps.begin(); sit!=deps.end(); ++sit) { ... } 

...或者你可以改變你的getDependencies的定義返回一個參考:

set<string>& ConcretePackage::getDependencies() { 
    return dependencies; 
} 

研究做它的原因單向vs.另一個留給學生練習。 :P


一些更多的注意事項:

  • 你不需要對零大小集合類特殊情況的測試,你要使用迭代器與。如果一個集合不包含元素,那麼該集合的.begin()將返回一個等於.end()的迭代器。上面的循環處理這種情況很好,並會立即退出。

  • 在代碼中明確調用operator+而沒有對返回值做任何事情表明您可能有某種副作用。很少有人希望像a = b + c這樣的表達式改變bc ......而像b->operator+(c);這樣的單行代碼表明你正在做某種事情。雖然技術上可行,但我會避免它。請參閱第2點:Operator overloading

  • 當您發佈代碼示例時,請務必使它們可讀並且不需要大量滾動條來顯示。如果您在預覽中注意到它正在放置長長的水平滾動條,則會排成一行。不要爲每個大括號使用單獨的行,而應將它們放在與條件相同的行上。 (無論你在你的代碼庫中,講話者用什麼約定要求的技術幫助時更好的在線)

(也提供上下文。如果不說這是功課和自己的設計,然後像我這樣的人會去谷歌嘗試,並找出你正在使用什麼樣的包管理器幸運的是,我發現你的程序員.stackexchange.com後...)

+0

你說得對,我應該提供上下文。我很簡短,我不想發佈太多的代碼。我已經在這個細分市場上進行了調整,並認爲這將是最相關的。 我最初沒有測試0,但在得到那個錯誤後,我認爲它可能以某種方式阻止它。如果你能通過查看代碼提供一些建議,我會很感激。 – nikhil

+1

@nikhil我發現你的問題(嗯,這個反正的原因)。更新。另外我注意到你的Makefile是錯誤的,可能會導致你很多挫折,因爲它不會在編輯後重建正確的文件。如果您打算使用make,那麼請閱讀一下以確保您正確使用它:http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html – HostileFork

+1

順便提一下,你應該使用運算符重載'+'作爲調用日誌函數的無意義方式。如果你必須證明運算符在某處過載,我相信你可以做更合理的事情,在運算符重載讓你從包中「添加」和「減去」依賴關係(例如)... – HostileFork