2012-02-09 3 views
3

あなたに提供されたAPIからの関数呼び出しのスタック使用をどのように判断できますか?関数の外観がわからず、APIにのみアクセスできます。例えば、私は考えることができるツールなどを使用せずに、いくつかのAPI関数呼び出しのスタック使用を見つけますか?

int main() { 
     // call some API function 
     some_func_called(); 

     // rest of your main 
    } 

唯一のことは、関数を呼び出す前に、既知のパターンとのスタックメモリを移入し、後から後に変更されたどのように多くの既知のパターンのバイトを参照してスタックをチェックすることです関数は戻ります。他のアイデア? (これはインタビューの質問でした)

+1

あなたのアイデアは素晴らしいと思います。 –

+1

「その他のアイデア?」と思っていますが、あなたのアイデアは良いと思いますが、代わりに言えば、プログラム内のメモリ領域から読み取り/書き込みの許可を取り除くことができるOSがありますsome_func_calledが落ちるまで使用可能なスタックスペース。スタックが潜在的に成長する場所を知っているか、推測する必要があります(あなたの「既知のパターン」のアプローチの問題もあります)。また、some_func_called()を複数回呼び出すことができない場合や、呼び出しごとに同じ量のメモリを使用しない場合、あなたは失敗点で磨きをかけながらアプリケーションを再実行する必要があります。 –

答えて

2

このように、完全にテストされていない場合、制限の問題がある可能性があります。スタックポインタがPUSHINGによって減少する場合にのみ機能します。したがって、これはすべてのハードウェアで移植できません。

#include <stdlib.h> 
#include <string.h> 

#define STK_CNT 65536 

size_t STK_fill() 
{ 
    volatile size_t i, cnt = 0; 

    volatile u_int32_t fill[STK_CNT]; 

    for(i = 0; i < STK_CNT; i++) 
    { 
     fill[i] = 0xDEADBEEFUL; 
    } 

    return cnt; 
} 

size_t STK_find() 
{ 
    volatile size_t i, cnt = 0; 

    volatile u_int32_t fill[STK_CNT]; 

    for(i = 0; i < STK_CNT; i++) 
    { 
     if(fill[i] == 0xDEADBEEFUL) 
     { 
      cnt++; 
     }else{ 
      break; 
     } 
    } 

    return ((STK_CNT - cnt) * 4); 
} 

void victim(char *po_str, const char *pi_str) 
{ 
    char str[1024]; 

    strcpy(str, "stk_TEST_"); 
    strcat(str, pi_str); 
    strcat(str, "_stk_TEST"); 

    strcpy(po_str, str); 
} 

int main() 
{ 
    int temp; 
    int used; 
    char str[4096] = {0}; 

    temp = (int)STK_fill(); 
    victim(str, "STK_tst_STK_tst_STK_tst_STK_tst_STK_tst_STK_tst_STK_tst_STK"); 
    used = (int)STK_find(); 

    printf("VICTIM function used %d bytes of stack\n", used); 

    return 0; 
} 
+0

返事をありがとう。これの実用的価値は何か? – Mir

+3

@Meeir:実用的価値...ソースコード内で再帰的な関数が実行時に実際の再帰を避けるように最適化されているか、失敗前の最大再帰深度のランタイム推定を可能にするかについて、いくつかの洞察を可能にするかもしれません。また、通常のスタックや例外処理のために(ハードコードされているシステムで)割り当てるようにコンパイラに依頼するための適切なサイズのスタックに関する有用な洞察でもあります。これは、予期しないほど高いメモリ使用量が望ましくないコピーを示していることの健全性チェックとして有用な洞察にすぎないかもしれません。しかし、すべての非常にハックアップ。 –

+1

@Meeir Aalie:の変数

には、victim関数によって実際に使用されたスタックバイトの数が格納されます。この関数を使ってスレッドのスタック使用量を最適化することができます。これは、Embedded Systems BTWと同様のことを行う必要があります。 Tony Delroyのコメントも参考になります。 – Malkocoglu

0

私はあなたの方法がそれを行う最も信頼できる方法だと思います。

現代のOSが必要に応じてスタックを増やす(つまりメモリを増やす)傾向があるという事実を利用する方法もあります。 Will the stack of a C program ever shrink?を参照してください。おそらく、この関数を呼び出して、スタックにコミットされたメモリの量をOSに問い合わせることができます。もちろん、これはOS特有のものであり、アーキテクチャー固有のものであり、全体としては第1のアプローチよりもはるかに面倒なものになりがちです。

+0

"OS質問"のアイデアは、以前のスタック使用量からの高いウォーターマークがテスト対象の関数のスタック使用量を超えないことを前提としています。 –

関連する問題