1

这个问题发生在很多繁忙的函数中间,所以我将尝试用伪代码来解释这个问题,希望它足够了。我对理解潜在问题和解决它同样感兴趣,所以除了修复之外,我希望能得到解释。谢谢!

'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 不会存储字符串!!! IE

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!

现在我感觉自己快要疯了......

4

1 回答 1

2

当您在内存分配器中崩溃时,您很少能将问题追溯到崩溃时被释放(或分配)的确切内存。分配器将进行健全性检查,通常会捕获释放无效指针的尝试(未指向某些分配开始的指针、堆边界外的指针、重复的释放等)。内存分配器崩溃的最常见原因是堆损坏。通常被释放的块使用块前面的小结构链接到其他空闲块。在释放的内存上写入或在分配的块之外写入会破坏这些指针并导致分配器崩溃。

我希望,如果您的备用程序在避免初始崩溃后运行足够长的时间,最终还是会发生另一次崩溃。您观察到的模式xx可能就像长度与..xx大不相同一样简单,因此是从不同的内存池分配的。x1x3

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

于 2012-11-11T21:38:40.417 回答