簡體   English   中英

迭代std :: set時出現分段錯誤 <std::string> 在C ++中

[英]Segmentation fault while iterating a std::set<std::string> in C++

我的代碼的這一部分(針對該項目 )給我一個分段錯誤。 源代碼可在此處獲得

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上找到。

我試圖通過調試器運行代碼,打印出* sit。 它會工作一段時間,然后崩潰。 我對gdb不太了解。

StackOverflow有一些“什么是分段錯誤?” 風格問答:

什么是細分錯誤?

理想情況下,您需要在具有調試器並且能夠逐行逐步執行代碼或放置斷點的環境中工作。 這可以幫助您隔離崩潰周圍的情況。 您在堆棧跟蹤中已經有一個行號-我們假設這是吸煙槍指向的行號:

cout<<*sit<<endl;

但是單步調試器可能會回答這樣的問題,例如這是否是第一次在循環中發生……如果不是,那么在哪個元素上發生。


更新 :查看您在GitHub上具有的這段代碼(不包括上面的代碼),我看到ConcretePackage::getDependencies() 通過值而不是通過引用返回集合。 這意味着每次呼叫成員時,都會獲得該集合的新副本。 來自不同容器的迭代器不應相互比較,即使它們是同一類型:

比較來自不同容器的迭代器

要解決此問題,您可以更改:

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;
}

研究方法以一種方式與另一種方式進行比較留給學生。 :P


一些注意事項:

  • 對於將要使用迭代器的集合類,您不需要針對零大小的特殊情況測試。 如果集合不包含任何元素,則該集合的.begin()將返回與.end()相等的迭代器。 您上面的循環可以很好地處理這種情況,並且可以立即退出。

  • 在代碼中顯式調用operator+而不對返回值做任何事情表明您可能會有某種副作用。 很少有人期望像a = b + c這樣a = b + c表達式可以改變bc ...以及像b->operator+(c);這樣的單行代碼b->operator+(c); 建議您正在執行某種操作。 盡管在技術上可行,但我會避免使用。 請參閱此處的第二點: 運算符重載

  • 當您發布代碼示例時,請嘗試使其保持可讀性,並且不需要太多滾動條即可顯示。 如果您在預覽中注意到它放置了較長的水平滾動條,請中斷排列。 不要將每個大括號使用單獨的行,而應將它們放在與條件相同的行上。 (無論您在代碼庫中使用哪種約定,在在線尋求技術幫助時,簡短的內容都越好。)

(還提供了上下文。如果您不說這是家庭作業和您自己的設計,那么像我這樣的人將使用Google搜索來確定您使用的是哪種程序包管理器。幸運的是,我找到了您的developers.stackexchange.com post ...)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM