2011-10-27 10 views
0

私はアンドロイドに移植しているVisual Studioプロジェクトを持っています。関数の呼び出しは以下の通りですなぜネストされた呼び出しで引数の値が変化し、セグメント化エラーにつながる

char* format1(const char* fmt, ...) { 
    char* buf = new char[1030]; 
    va_list ap; 
    va_start(ap, fmt); 
    vsprintf(buf, fmt, ap); 
    va_end(ap); 
    return buf; 
} 

char* format2(const char* fmt, ...) { 
    va_list ap; 
    va_start(ap, fmt); 
    char* s = format1(fmt, ap); 
    va_end(ap); 
    return s; 
} 

char* s = format2("%*.*d", 8, 8, 9910153); 

私は上記に関するクエリのカップルを持っている私は、下の機能に似た関数呼び出しでセグメンテーション違反の問題に直面しています:

「function2」の呼び出しのためにgdbのコードをステップ実行すると、次のように表示されます。 形式(fmt = 0x4) これはなぜですか?

'function1'が呼び出されると、gdbは次のように表示します。 format1(fmt = 0x15be30 "メモリ内のランダムな値") どのようにfmtの値が変更されましたか?また、fmtの値に応じて、セカンドコールがセグメンテーション違反につながります。

上記の動作を説明する助けがあれば、大歓迎です。

+0

。 – user786653

答えて

3

format1は、可変の引数セットをとります。va_listではなく、 1つの(非整数)引数を渡します。フォーマット文字列には、3つの整数引数が必要です。そのため、未定義の動作が発生します。

それはのようなものでなければなりません:ちょうど `va_list`として` ap`を渡すか、それを抽出するために、 `va_arg`を使用

char* format1(const char* fmt, va_list ap) { 
    char* buf = new char[1030]; 
    vsprintf(buf, fmt, ap);  
    return buf; 
} 
+0

これは、デバッガがfmt = 0x4を報告する理由を尋ねた質問には答えません。 'vsnprintf'の未定義の振る舞いは、関数がまだ呼び出されていないために起こります。 –

+0

@RobKennedy:私はタイトルの質問に答えています:なぜセグメンテーションがありますか?私は、特定のデバッガがどのようにスタックの破損が存在するかのように振る舞うかもしれないとは全く考えていません。 –

+1

'format2'への入力時に(実際には' format1'へのエントリ時でさえ)、スタックの破損はまだ起こっていません。これは 'vsnprintf'が呼び出されるまでは起こりません。 –

関連する問題