2012-06-09 23 views
5

初心者の質問かもしれませんが、関数がローカル変数へのポインタを受け入れることを防ぐ方法がC/C++にありますか?コンパイラは、ポインタを返すことができないという警告が生成されますローカルポインタの防止

int* fun(void) 
{ 
int a; 
return &a; 
} 

は、このコードを考えてみましょう。これを考慮してください:

int* g; 

void save(int* a) 
{ 
g = a; 
} 

void bad(void) 
{ 
int a; 
save(&a); 
} 

これは警告なしでコンパイラを通過しますが、これは悪いです。これが起こらないようにする属性や何かがありますか?私。次のようなものがあります:

void save(int __this_pointer_must_not_be_local__ * a) 
{ 
g = a; 
} 

誰かが答えを知っている場合は、事前に感謝します。

+1

コードレビュー? lintなどのコードプロファイラー? –

+0

コードレビュー、静的解析。あなたが求めているのは、実際には非常に複雑なことです。 –

+1

私が 'void f(){int b; '' int * p = new int(); save(p); save(&b);/* do stuff */save(NULL);} '?変数がローカルであるとは限りません。 ); delete p; ' –

答えて

0

いいえ、ヒープオブジェクトへのポインタからローカルへのポインタを伝える信頼できる移植可能な方法はありません。宣言的にこれを防ぐ方法もありません。

特定のシステムのメモリレイアウトに依存するハックは、実行時に不特定の動作(例としてthis answerを参照)を呼び出すことによって動作しますが、試してみることにした場合は、あなた自身で行います。

+0

コンパイラが関数がローカルポインタを返そうとしているときを認識し、OPが示唆しているように属性があった場合、なぜコンパイラは同じロジックを使って警告を生成できませんでしたか? –

+0

@ScottHunterコンパイラは、コードを静的に解析することによって確実に判定することができないためです。ポインタをグローバル変数に格納することは、チェックを回避できる唯一の方法です。構造体メンバに格納したり、バイト配列に変換したりできます。小切手を信用できないものにすることは、その目的を破るでしょう。 – dasblinkenlight

+0

返品確認とはどのように違いますか? –

2

デバッグヒープ(デフォルト)を使用して、デバッグビルドの少なくとも一つの方法があります:

//d:\Program Files\Microsoft Visual Studio ?\VC\crt\src\dbgint.h 
\#define nNoMansLandSize 4 
typedef struct _CrtMemBlockHeader 
{ 
    struct _CrtMemBlockHeader * pBlockHeaderNext; 
    struct _CrtMemBlockHeader * pBlockHeaderPrev; 
    char *      szFileName; 
    int       nLine; 
    size_t      nDataSize; 
    int       nBlockUse; 
    long      lRequest; 
    unsigned char    gap[nNoMansLandSize]; 
    /* followed by: 
    * unsigned char   data[nDataSize]; 
    * unsigned char   anotherGap[nNoMansLandSize]; 
    */ 
} _CrtMemBlockHeader; 
\#define pbData(pblock) ((unsigned char *)((_CrtMemBlockHeader *)pblock + 1)) 

ギャップで終わる割り当てヘッダは、ありますが、それほど大きく確率はありません前に0xFDFDFDFDがあるだろうポインタ - 完璧ではありませんが、手助けかもしれません...

if (\*((int\*)pointer-1) == 0xFDFDFD) { // stack pointer }