- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
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 中 - 已损坏。例如,它可能变成 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
( 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/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!