問題タブ [gcc-extensions]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - GCC - 関数が戻った後に実行が継続する場所を変更する
GCCでこのようなことをすることは可能ですか?
- これは、プラットフォーム固有のアセンブリを使用せずに、C および GCC 拡張機能を使用して移植可能な方法で実現できますか?
- スタック状態は、通常の戻りポイントと変更された戻りポイントの間で変化しないため、通常の戻りからスタックとレジスタの状態を復元するコードを再利用することは可能ですか?
- 関数がインライン化される場合とされない場合があることを考慮して、呼び出された場合はリターン アドレスを変更する必要があります。インライン化されている場合は、コード パスのみを変更する必要がありますが、現在の関数のリターン アドレスは変更しないでください。コードが壊れる可能性があるためです。
- 代替リターンポイントはラベルである必要はありませんが、GCC のラベル拡張のアドレスがこの状況で役立つことを願っています。
意図を明確にするために-それはエラー処理に関するものです。この例は、物事を説明するための最小限のものです。エラーが発生した場合に実行を停止するために、これをより深いコンテキストで使用するつもりです。また、2 つの戻り点の間に余分なローカル変数が追加されていないため、状態が変化しないと仮定しますが、これについては間違っている可能性があります。そのためにlongjmp
、ジャンプバッファーを使用、設定、および渡すオーバーヘッドを節約します。
その意図は、実際のコードでなぜ、どのように意味があるかではなく、私が達成したいことを示すことであるため、この例は「意味があります」。
単純に foo() から値を返し、bar() を何らかの条件で返すか実行するよりも、あなたのアイデアが単純なのはなぜですか?
それは単純ではなく、あなたが提案することは実際には適用できず、些細な例のコンテキストでのみ適用されますが、次の理由により優れています。
1 - 値を追加で返す必要はありません
2 - 値の追加チェックは必要ありません
3 - 追加のジャンプは必要ありません
私はおそらく、この時点で、すべての明確化と説明を経て、目標が明確になるはずだと誤って想定しています。アイデアは、追加のオーバーヘッドなしで深い呼び出しチェーンから「エスケープ コード パス」を提供することです。コンパイラが生成したコードを再利用して、前の呼び出しフレームの状態を復元し、関数が戻った後に実行を再開する命令を変更するだけです。成功すると「エスケープ コード パス」がスキップされ、発生した最初のエラーがそこに入ります。
Basile Starynkevitch によるlongjmp
「効率的」であり、「10 億の longjmp でも妥当なままである」という主張についてはsizeof(jmp_buf)
、156 バイトというかなりの量が得られます。後で復元できるようにします。これらは多くの操作であり、それを10億回行うことは、「効率的」および「合理的」という私の個人的な理解からはほど遠いものです。つまり、10 億個のジャンプ バッファー自体が145 ギガバイトを超えるメモリだけであり、CPU 時間のオーバーヘッドもあります。そのような「合理的な」余裕さえあるシステムはそれほど多くありません。
c - 各関数インスタンスでサイズが異なるVLAを返す方法は?
構造内で VLA を宣言できるようにする、優れた GCC 拡張機能を使用しています。今のところ、この方法で VLA を関数に (値で) 渡す方法を見つけました。また、非常に限られたコンテキストで返す方法を見つけました。
この例の関数コードは次のとおりです。
上記の例は、テスト目的で設計されています (特に、コンパイルされたバイナリ コードを比較するため)。
ただし、返される配列のサイズは関数の異なる呼び出し間で変化しないため、これはかなり制限されています。
返された配列のサイズを、関数パラメーターの 1 つまたはこの関数の他のローカルと等しくするにはどうすればよいでしょうか。
alloca
割り当てられたメモリは関数終了 (IRC) ですぐに破棄されるため、この場合は役に立たないと思います。
私はこのようなものを書きたい:
言い換えれば、疑問符内の型は何でしょうか? または、他の解決策があるかもしれません(ただし、を使用せずにmalloc
)?
このような関数の理論的な使用法では、返された構造体のサイズを呼び出し元が利用できないため、返された値を格納するために理論的には別の型が必要になります (これを回避する方法がない限り?)。しかし、一見すると、次のようになります。
このようなことをすると:
func5
VM の戻り値の型は、その引数またはローカル変数に依存するため、機能しません。ただし、この関数はまだ定義できないため、現時点ではすべて理論上のものです。
c - 属性 (noinline) のサポートに必要な ARM コンパイラのバージョンは何ですか?
特定の属性をサポートするために必要な ARM コンパイラ (armcc) のバージョンを確認する方法がわかりません。
たとえば__atribute__((noinline))
?
http://www.keil.com/support/man/docs/armcc/armcc_chr1359124975804.htmを参照して ください。
c - __extension__ と -std=c99 を混在させることはできますか?
void *
標準では、関数へのポインターと関数へのポインターの間の変換は許可されていません。
6.3.2.3:8 あるタイプの関数へのポインターは、別のタイプの関数へのポインターに変換され、再び元に戻される場合があります。結果は元のポインタと等しくなります。変換されたポインターを使用して、ポイント先の型と互換性のない型を持つ関数を呼び出す場合、動作は未定義です。
glib/gtk には、この規則を破る関数がいくつかあります。例を次に示します。g_signal_handlers_block_by_func
a で大文字に変換する典型的な例GtkEntry
:
gpointer
typedef
forvoid *
であり、次g_signal_handlers_unblock_by_func
を使用して実装されgpointer
ます。
したがって、 を使用してこのコードをコンパイルする-std=c99
と、次の警告が表示されます。
そして、コンパイラを沈黙させるために私が見つけることができる唯一の方法は、次を使用すること__extension__
です:
長いプリアンブルで申し訳ありませんが、ご覧のとおり、glib / gtk は gcc 拡張機能を使用しており、シグナル ハンドラーを使用-pedantic
するプログラムをモードで (警告なしで)コンパイルする方法はありません。gtk
私の質問は:
-std=c99
と組み合わせて使用できますか、__extension__
または強制的に使用でき-std=gnu99
ますか?
言い換えれば、__extension__
拡張機能を使用してコンパイルすることを意味する (強制する) か、コンパイラを黙らせるための単なる指示であり、私のプログラムは未定義の動作の下で動作していますか?
c - gcc/clang C 拡張機能を使用してマクロ引数がポインターかどうかをテストする
C 言語 (C11) に対する gcc/tcc/clang の拡張機能を使用して、マクロ引数にポインター型があるかどうかを検出することは可能ですか?
詳細: 私は単一間接ポインターを取るマクロを使用していますが、対応する「コンストラクター」マクロが取るものであるため、そのポインターにポインターを渡したくなるのですが、そうするとエラーになるので、現在、次のようなものを使用しています:
自分から自分を守るために。実装するより良い方法はありISPTR()
ますか?