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 によると、関数が parameters を使用してスタックに到着していること("", 31135568)
です。プログラムは 31 メガバイトを割り当てようとして失敗し、アサートにヒットして終了します。
上記のフレームdulpicateStringValue()
を GDB で調べると、最初のパラメーターがヒープ上の小さな文字列を指し、2 番目のパラメーターが省略された状態で呼び出されていることがわかります。言い換えれば、私が知る限り、関数呼び出しはパラメーターのガベージ値を誤って取得しています。
私は本当にこれに困惑しています。私が持っている唯一のアイデアは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