仅在传递变量时才对std :: string析构函数执行c ++ seg fault

时间:2012-11-11 21:22:57

标签: c++ segmentation-fault destructor stdstring

这个问题发生在很多忙碌函数的中间,所以我将尝试用伪代码来解释这个问题,希望它足够了。我同样有兴趣了解解决它的基本问题,所以除了修复之外,我还要感谢解释。谢谢!

'methodOne'从另一个函数中检索std :: string xx,并将它与字符串x1,x2和x3(全部来自新对象)一起发送到'methodTwo'。

bool methodOne(...) {
    Object1 obj = Object1(...);
    string xx = obj.someFunction(...);
    methodTwo(xx, obj.getX1(), obj.getX2(), obj.getX3() );
    ...
    return true;
}

'methodTwo'(在Object2中)然后将这些字符串组合成一个向量,并将它们传递给'methodThree'。

bool Object2::methodTwo(const string xx, const string x1, const string x2, const string x3) {
   vector<string> holder;      // alternate - comment out this line
   holder.push_back(xx);       //             and this line,
   // vector<string> holder(1, "test");    // alternate - uncomment this line
   holder.push_back(x1);
   holder.push_back(x2);
   holder.push_back(x3);
   ...
   obj3.methodThree( holder );
   ...
   return true;
}          // line 443 - where error is backtraced to

最后,'methodThree'最终会创建一些文件,所有四个字符串都会打印到其中一个文件中。

运行程序,我从gdb获得了一个分段错误:

Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 0x00007fff8f1e3aa2 in std::basic_string<char, std::char_traits<char>, std::allocator<char>
>::~basic_string () (gdb) where
#0  0x00007fff8f1e3aa2 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string ()
#1  0x0000000100009f18 in std::_Destroy<std::string> ()
#2  0x0000000100009f3e in std::__destroy_aux<std::string*> ()
#3  0x0000000100009f9f in std::_Destroy<std::string*> ()
#4  0x0000000100009fd7 in std::_Destroy<std::string*, std::string> ()
#5  0x0000000100060115 in std::vector<std::string, std::allocator<std::string> >::~vector (this=0x7fff5fbfd488) at stl_vector.h:271
#6  0x0000000100013b9f in Station::methodTwo (this=0x7fff5fbff110, foreFN=@0x7fff5fbfdf08, startDT=@0x7fff5fbfded8, stopDT=@0x7fff5fbfdea8, numElems=169, tCase=0x7fff5fbfe7c8) at Station.cpp:443
#7  0x0000000100002b45 in methodOne ()
#8  0x000000010000707a in main ()

在'methodTwo'中,如果我用一些随机测试字符串替换字符串'xx',则错误消失。所以问题必须是'xx'---这也是'methodOne'中唯一不是来自Object1 obj的字符串。

我在想一些构造函数实际上并没有复制字符串(复制术语是浅层的吗?)所以我尝试过像调用methodTwo这样的事情

methodTwo( string(xx), obj.getX1() ...)

或构建矢量时,使用

之类的东西
holder.push_back( string(xx) );

但这些都没有奏效。

我完全失去了,我很感激任何帮助/提示。我知道它很烦人,因为我没有提供可以重现问题的连贯代码,甚至是实际的代码---但希望这对于比我自己更聪明的人看到的东西就足够了。

感谢


新奇怪:

从下面的评论中,听起来很可能实际错误是在其他地方,感染堆。但是,因为xx仅通过从obj检索而不是来区分,所以我尝试将xx添加到对象中 - 即在之前调用的另一个方法中,变量xx被设置为与之前相同的结果值...

string Object1::someFunction(...) {
    ...
    string val = ...;
    setXX(val);
    cout << getXX() << endl;         // this *correctly* prints the value of xx
    ...
    return val;
}
void Object1::setXX(string temp) { xx = string(temp); }
string Object1::getXX() { return xx; }

然后我在methodTwo调用中检索xx:

methodTwo(obj.getXX(), obj.getX1() ... );

并且停止了错误,但 xx 不会存储字符串!!! I.e。

obj.someFunction(...);          // this is able to set and retrieve xx
cout << obj.getXX() << endl;    //  prints **blank line!!**
methodTwo(obj.getXX(), obj.getX1() ...);   // no more error, x1 x2 x3 are fine, xx is empty!

现在我觉得我疯了......

1 个答案:

答案 0 :(得分:2)

当您在内存分配器中崩溃时,很少可以将问题跟踪到崩溃瞬间释放(或分配)的确切内存。分配器将具有健全性检查,通常会捕获尝试释放无效指针(指向不指向某些分配的开头的指针,超出堆边界的指针,重复释放等)。内存分配器崩溃的最常见原因是堆损坏。经常释放的块被链接到其他空闲块,使用块前面的小结构。在释放的内存上写入或在已分配的块之外写入将破坏这些指针并导致分配器中的崩溃。

我希望如果你的 alternate 程序在避免初始崩溃后运行的时间足够长,那么最终会发生另一次崩溃。您使用xx观察到的模式可能就像xx的长度与x1 ... x3的差异一样简单,因此可以从不同的内存池中分配

这是一个尝试的测试:如果您只是将return放在methodThree的顶部,程序是否仍会崩溃?