ASI 有一个 C++ 函数,如下所示:
static const unsigned int unknown = (unsigned)-1;
static inline char *
duplicateStringValue( const char *value,
unsigned int length = unknown )
{
if ( length == unknown )
length = (unsigned int)strlen(value);
char *newString = static_cast<char *>( malloc( length + 1 ) );
ASSERT( newString != 0, "Failed to allocate string value buffer" );
memcpy( newString, value, length );
newString[length] = 0;
return newString;
}
(这恰好在 jsoncpp 库中,但我很确定这与问题正交)
问题是,根据 GDB,该函数是带着参数到达堆栈的("", 31135568)
。该程序尝试分配 31 兆字节但失败,命中断言并死亡。
通过使用 GDB 检查上面的框架dulpicateStringValue()
,我可以看到调用它时第一个参数指向堆上的一个小字符串,而第二个参数则省略了。换句话说,据我所知,函数调用错误地获取了参数的垃圾值。
我真的被这件事难住了。我唯一的想法是dulpicateStringValue()
在此之前成功调用了很多次,但此时堆栈深度约为 25 帧,比平时深得多(据我所知)。也许堆栈和堆正在相互碰撞和乱涂乱画?
如果有人有一些见解或遇到类似的事情,我很想听听。
编辑:在回答问题时,该函数被称为
value_.string_ = duplicateStringValue( other.value_.string_ );
其中 other.value_ 是由 GDB 描述为的联合
value_ = {int_ = 34536679944, uint_ = 34536679944,
real_ = 1.7063387081744787e-313, bool_ = 8,
string_ = 0x80a8bea08 "boolean", map_ = 0x80a8bea08}
工会代码:
union ValueHolder
{
LargestInt int_;
LargestUInt uint_;
double real_;
bool bool_;
char *string_;
ObjectValues *map_;
} value_;
编辑 2: @MarkRansom 询问参数是如何进入堆栈的。事实上,它们不是,GDB 直接从寄存器中读取它们:
(gdb) f 1
#1 0x000000080663377e in duplicateStringValue (value=0x80aac9a10 "", length=31135568) at json_value.cpp:60
60 ASSERT( newString != 0, "Failed to allocate string value buffer" );
(gdb) p &length
Address requested for identifier "length" which is in register $rsi
(gdb) p &value
Address requested for identifier "value" which is in register $r13