開始アドレスは関数名から取得できますが、関数の終了アドレスを見つける方法は? 面接でこんな質問をされました。
私が書いた関数 f() がテキスト セクションを越えて、隣接するセクション (データ セクション) を書き直したとします。この状況をどのように処理できますか? また、C コードで処理する必要があるとも付け加えました。シンボル マップ ファイルを表示してアドレスを取得する必要はありません。
開始アドレスは関数名から取得できますが、関数の終了アドレスを見つける方法は? 面接でこんな質問をされました。
私が書いた関数 f() がテキスト セクションを越えて、隣接するセクション (データ セクション) を書き直したとします。この状況をどのように処理できますか? また、C コードで処理する必要があるとも付け加えました。シンボル マップ ファイルを表示してアドレスを取得する必要はありません。
&&
GCC では、演算子 (yes - &&
, not )を使用して、ラベルのアドレスを取得できます&
。
これは次のように使用できます。
void f(void) {
printf("Start %p End %p\n", f, &&f_end);
f_end: return;
}
ラベルの後にいくつかのエピローグ コードがあるため、これで正確に終了することはできませんが、インタビューの回答としては十分だと思います。
C 標準では、関数の終了アドレスなどの存在は保証されていません。
実際には、関数は必ずしもメモリの単一の連続した部分ではなく、オーバーラップしたり、コード オプティマイザーによって複数の部分に分割されたりする可能性があります。
そのため、実行時にこれを見つける方法はありません。
さらに、GetProcAddress から取得するか、関数のアドレス (関数ポインターの場合) を取得することによって取得する「開始アドレス」が、コードの実際の場所と関係があるという保証はありません。
関数ポインターが保証するのは、アドレスを介して呼び出すと、関数が実行されることだけです。コードが実際に存在することを保証するものではありません。たとえば、サンクのアドレスだけかもしれません。
コンパイラはおそらくアセンブリ リスト ファイルを生成でき、リンカーはおそらくマップ ファイルを生成できます。これらにより、特定の機能が手動でどれくらいの長さかを確認できます。Cプログラム自体からサイズを決定する必要があるかどうかはわかりません。