2012-06-09 21 views
5

Vielleicht ist es eine neue Frage, aber gibt es eine Methode in C/C++, um zu verhindern, dass eine Funktion einen Zeiger auf eine lokale Variable akzeptiert?Verhindern von lokalen Zeigern

Betrachten Sie diesen Code:

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

Der Compiler erzeugt eine Warnung wird, dass der Zeiger nicht zurückgegeben werden können. Betrachten Sie jetzt folgendes:

int* g; 

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

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

Dies wird durch den Compiler ohne eine Warnung passieren, die schlecht ist. Gibt es ein Attribut oder etwas, um dies zu verhindern? I.e. etwas wie:

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

Vielen Dank im Voraus, wenn jemand die Antwort kennt.

+1

code reviews? ... Code-Profiler wie Flusen? –

+0

Codeüberprüfungen, statische Analyse. Was du verlangst, ist in der Tat sehr, sehr komplex. –

+1

Was wäre, wenn ich 'void f() {int b; save (&b);/* tu stuff */save (NULL);} '? Es ist nicht unbedingt die Tatsache, dass die Variable" local "ist, was wichtig ist. Das wäre auch schlecht.' int * p = new int(); save (p); löschen p; ' –

Antwort

0

Nein, es gibt keine zuverlässige und portable Möglichkeit, einem Zeiger auf ein Heap-Objekt einen Zeiger auf local mitzuteilen. Es gibt auch keine Möglichkeit, dies deklarativ zu verhindern.

Es gibt Hacks, die abhängig vom Speicherlayout Ihres speziellen Systems sind, die zur Laufzeit durch Aufrufen eines nicht spezifizierten Verhaltens funktionieren (siehe this answer für ein Beispiel), aber Sie sind allein, wenn Sie sich entschließen, sie auszuprobieren.

+0

Wenn jedoch der Compiler-Nock erkennt, wenn eine Funktion versucht, einen lokalen Zeiger zurückzugeben, und wenn ein Attribut vorhanden war, wie das OP vorschlägt, warum konnte der Compiler nicht dieselbe Logik verwenden, um eine Warnung zu generieren? –

+0

@ScottHunter Weil der Compiler es nicht zuverlässig ermitteln kann, indem er den Code statisch analysiert. Das Speichern eines Zeigers in einer globalen Variablen ist nur eine Möglichkeit, mit der Sie die Prüfung umgehen können. Sie können sie in einem Strukturelement speichern, in ein Array von Bytes konvertieren und so weiter. Das Hinzufügen eines so unzuverlässigen Schecks würde den Zweck zunichte machen. – dasblinkenlight

+0

Wie unterscheidet sich das von der Rückkehrprüfung, die implementiert wird? –

2

Es gibt mindestens eine Art und Weise für Debug-Build Debug-Heap verwenden (Standard):

//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)) 

Es gibt eine Zuordnung Header, der mit Spaltenden, so ist es nicht große Wahrscheinlichkeit wird 0xFDFDFDFD sein, bevor die Zeiger - nicht perfekt, aber kann helfen ...

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