2011-11-29 138 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

相关问题