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 によると、関数が 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
4

0 に答える 0