gpt4 book ai didi

c++ - 从函数返回时指针损坏

转载 作者:行者123 更新时间:2023-11-30 01:15:01 25 4
gpt4 key购买 nike

TL;DR:当我在 OS X Yosemite 下的 Mac 上运行我的 C++ 程序时,指针在函数返回时损坏。我该如何阻止它发生? (为什么?)


this sample program , 我有一个 category_map<T> 类型的数据结构这实际上只是一个

map<string, list<pair<string, T> > >

category_map类有几个方法,包括 get(string& name)这拉动了 list存储在给定的 name 下并返回 T从该列表的第一个元素。就我而言,T是指针类型。代码从第一个 pair 检索的指针在list - 应该是 p在下面的代码 list 中 - 是有效的。调试器 session 显示 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 中在下面的下一个代码 list 中 - 已损坏。例如,它可能变成 0x3000100809c000x5000100809c00 .损坏的指针始终是原始指针,在 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

( more context ) 但这并没有太大帮助,因为它不是 C/C++ 函数的一部分,我的汇编不够流利,无法理解它在大规模上的作用,而且 backtrace是垃圾所以我不能把代码放在上下文中。 (我还在破坏指针的指令之前捕获了 values of the registers,以防出于某种原因有帮助。)

自从我实例化category_map<T>只有指针类型,我可以更改 get 的返回类型至 T (而不是 T& )这似乎确实解决了(或至少解决了)问题。但是如果它可以容纳大对象并通过引用返回它们,它会使数据结构更有用,我认为这应该是可能的。另外,无论我在编码时犯了什么错误,我都想理解,所以我不会再犯了。任何人都可以指出我做错了什么,以及在不更改 API 的情况下修复它的正确方法吗?

最佳答案

list_type the_list = map_iterator->second;

你制作了 map_iterator->second 的拷贝。 the_list 是一个函数局部对象。然后

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++ - 从函数返回时指针损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29236318/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com