1

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
4

0 回答 0