从函数返回时指针已损坏
Pointer corrupted while returning from a function
TL;DR:当我在OS X Yosemite下的Mac上运行C++程序时,当函数返回时,指针会损坏。我该如何阻止它的发生?(为什么?)
在这个示例程序中,我有一个类型为category_map<T>
的数据结构,它实际上只是一个
map<string, list<pair<string, T> > >
category_map
类有几个方法,包括get(string& name)
,它提取存储在给定name
下的list
,并从该列表的第一个元素返回T
。在我的例子中,T
是一个指针类型。代码从list
中的第一个pair
检索到的指针(在下面的代码列表中应该是p
)是有效的。调试器会话显示,函数最后一行的p
的值(在析构函数运行之前的大括号)是一个有效的内存位置,比如0x100809c00
。
T& get(const string& name) const {
cerr << "searching for " << name << endl;
typename super::const_iterator map_iterator = super::find(name);
// the real code doesn't assume it will be found
list_type the_list = map_iterator->second;
T& p = the_list.front().second;
cerr << "found " << val_loc_string<T>(p) << endl;
return p;
}
然而,当我在Mac(OS X Yosemite)上编译和运行代码时,而不是在Linux上,在清理该函数的过程中,有东西会写入内存中的同一位置,因此返回的指针(存储在下面列出的下一个代码中的变量ip
中)已损坏。例如,它可能变成0x3000100809c00
或0x5000100809c00
。损坏的指针始终是原始指针,在8字节地址的第二个最高有效字节中设置了一个或几个额外的位。
int main(const int argc, const char** argv) {
category_map<int*> imap;
int a;
imap.add("Q1", "m", &a);
imap.add("Q1", "r", &a);
imap.add("Q2", "m", &a);
int* ip = imap.get("Q1");
cerr << "return value: " << val_loc_string<int*>(ip) << endl;
cout << *ip << endl;
}
使用GDB(通过MacPorts安装),我已经确定了将额外位写入内存位置的特定指令。
0x00007fff93188279: cmp $0x2,%eax
0x00007fff9318827c: jb 0x7fff9318828d
0x00007fff9318827e: shl $0x4,%rax
=> 0x00007fff93188282: mov %r10w,-0x2(%rax,%rdx,1)
0x00007fff93188288: mov %r10w,0x10(%rdx)
0x00007fff9318828d: test %r10w,%r10w
0x00007fff93188291: jne 0x7fff93188299
(更多上下文),但这并没有多大帮助,因为它不是C/C++函数的一部分,我对汇编不够流利,无法理解它在大规模执行什么,而且回溯是垃圾,所以我无法将代码放在上下文中。(我还捕获了在损坏指针的指令之前的寄存器值,以防出于某种原因有帮助。)
由于我只使用指针类型实例化category_map<T>
,因此我可以将get
的返回类型更改为T
(而不是T&
),这似乎确实解决了(或至少解决了)问题。但是,如果数据结构可以容纳大型对象并通过引用返回它们,那么它会使数据结构更普遍地有用,我认为这应该是可能的。另外,无论我在编码过程中犯了什么错误,我都想理解,这样我就不会再犯了。有人能指出我做错了什么,以及在不更改API的情况下修复它的正确方法吗?
使用
list_type the_list = map_iterator->second;
您制作了一份map_iterator->second
。CCD_ 21是一个函数局部对象。然后
T& p = the_list.front().second;
return p;
返回一个引用,该引用与此函数本地对象的寿命一样长,并且在函数保留时被销毁。该引用挂起。
在我看来,你似乎不打算复制这份名单,所以
// +------ const because get() is const-qualified
// v v-- reference
list_type const &the_list = map_iterator->second;
// v-- const because the_list is const
T const& p = the_list.front().second;
如果可以使get() const
返回一个T const &
1,则应该修复它。否则,您会遇到试图从const
成员函数返回对非常数成员的引用的问题;这将破坏const的正确性,因此是被禁止的(如果允许,则可以通过该引用更改常量对象)。
1您也可以让get const()
返回一个值而不是一个引用,但似乎没有理由强制复制。
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 为什么C中的通用链表中存储的数据已损坏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 变量周围的堆栈'...'已损坏
- 运行时检查失败 #2 变量"A"周围的堆栈已损坏
- 两个垫子的 OpenCV 数据是相同的,但使用 Mat::at 检索时的值已损坏
- 运行时检查失败 #2 - 变量"e"周围的堆栈已损坏。发生
- 变量周围的堆栈'sortArray'已损坏
- 变量周围的堆栈'folderPath'已损坏
- 在为 iOS 构建 aws-sdk-cpp 时,cmake 上的 CXX 编译器错误已损坏
- 运行时检查失败 #2 - 变量周围的堆栈'...'已损坏
- AES-128 CFB-8解密的前16个字节已损坏
- 运行时检查失败 #2 - 变量"l1"周围的堆栈已损坏
- C++:此代码可以编译,但引发运行时检查失败 #2 - 围绕变量周围的堆栈'num'已损坏。发生
- 图像在本地主机上显示已损坏
- 检查工作正常的 CXX 编译器:/cygdrive/c/cygwin64/bin/clang++ -- 已损坏
- C++指针:数组的堆栈已损坏
- 指针函数参数已损坏,堆栈已损坏
- 从函数返回时指针已损坏
- 调用 C++ 成员函数指针:此指针已损坏