4

簡単な例の下に、標準的な方法でバラディック引数を使用する c 関数があります。

    void func(parameter,...) {
     va_list args;
     va_start(args, parameter);

     //process args
     v1 = va_arg(args,sometype);
     v2 = va_arg(args,sometype);
        ...
     vn = va_arg(args,sometype);

     va_end(args);
}


//call func

func(parameter, p1, p2, ..., pn);

armv7s 以下のすべてのデバイス、および 64 ビット シミュレータを含むすべてのシミュレータで、これは成功し、v1 から vn への変数が p1 から pn に割り当てられますが、これを arm64 で実行すると、可変長リストが逆になっているように見えます ( v1 = pn, v2 = pn-1, ..., vn = p1)

これに対する修正はありますか?それとも、この変更を説明するドキュメントを見逃したのでしょうか?

ありがとう

編集:

この問題の重要な要素について言及するのに失敗しました。非可変関数を一般的な可変関数でスウィズルしようとしていました。

注: 使用されているコンパイラは Apple LLVM 5.0 でした

4

3 に答える 3

2

これは、引数が関数に渡される方法の変更に関係していると思われます。

これを行うには 3 つの方法があります:レジスター内スタック上、および引数の数と型に応じて両方を組み合わせたものです。ABI が準拠している規約に関して、ARMv6、ARMv7、および ARM64 アーキテクチャ間で違いがあるようです。

実際の規則に関係なく、コンパイラはこれを透過的に処理する必要があるため、ツールチェーンが標準に従って動作しない場合は、ツールチェーンの更新を検討する必要がある場合があります (質問ではコンパイラについて言及していませんが、これが重要です)。

さまざまなアーキテクチャ バージョンのさまざまな呼び出し規則に関するApple のドキュメントは、コンパイラによって考慮されていない変更を追跡するのに役立つ場合があります。

ARM が引数が渡されることを期待する方法の詳細については、ARM アーキテクチャのプロシージャ コール標準のセクション 5.5 (ARMv6、ARMv7、および64 ビット バージョンの ABI のセクション 5.4)を参照してください。

于 2013-12-16T22:04:07.990 に答える
1

まず、妥当な時間内に応答できなかったことをお詫び申し上げます。私は先月頭を下げていました。

この質問を Apple フォーラムに投稿しましたが、パラメーターが可変長関数にパックされる方法は、非可変長関数がパラメーターをパックする方法とは異なるようです。

したがって、これは armv7 および armv7s では機能しますが、arm64 での機能や、高レベルの最適化が適用されている場合でも、これに依存することはできません。

これが本当なら、ABI に違反しているように感じますが、私はそれが何であるかを受け入れます。

于 2014-01-17T17:50:21.057 に答える
0

可変引数は、呼び出し元と呼び出し先で同じ型を使用する場合にのみ機能します。たとえば、1 を渡して NSInteger として読み取ろうとすると、コンパイラのバグではなく、プログラマが varargs を理解していないため、64 ビットでは失敗します。

失敗するコードはまだ見たことがありません。

于 2014-05-24T17:47:11.730 に答える