2012-06-09 23 views
5

Quizás sea una pregunta para principiantes, pero ¿hay algún método en C/C++ para evitar que una función acepte un puntero a una variable local?Prevención de punteros locales

consideran este código:

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

El compilador generará una advertencia de que el puntero no puede ser devuelto. Ahora considere esto:

int* g; 

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

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

Esto pasará por el compilador sin una advertencia, lo que es malo. ¿Hay algún atributo o algo para evitar que esto suceda? Es decir. algo como:

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

Gracias de antemano si alguien sabe la respuesta.

+1

código comentarios? ... perfiles de código como pelusa? –

+0

Revisiones de código, análisis estático. Lo que está pidiendo es de hecho muy, muy complejo. –

+1

¿Qué sucede si quiero hacer 'void f() {int b; save (&b);/* do stuff */save (NULL);} '? No es necesariamente el hecho de que la variable sea" local "lo que importa; Esto también sería malo.' int * p = new int(); save (p); eliminar p; ' –

Respuesta

0

No, no hay una manera confiable y portátil de indicar un puntero a local desde un puntero a un objeto de pila. No hay forma de evitar declarativamente esto, tampoco.

Existen hacks que dependen del diseño de la memoria de su sistema particular que funcionan en tiempo de ejecución invocando un comportamiento no especificado (ver this answer para un ejemplo), pero usted está solo si decide probarlos.

+0

Pero si la cámara del compilador reconoce cuándo una función intenta devolver un puntero local, y si había un atributo como sugiere OP, ¿por qué el compilador no podría usar la misma lógica para generar una advertencia? –

+0

@ScottHunter Porque el compilador no puede determinarlo de manera confiable al analizar estáticamente el código. Almacenar un puntero en una variable global es solo una forma de eludir el control: puede almacenarlo en un miembro de estructura, convertirlo en una matriz de bytes, y así sucesivamente. Agregar un cheque tan poco confiable vencería el propósito. – dasblinkenlight

+0

¿Cómo es eso diferente del cheque de retorno, que se implementa? –

2

hay al menos una forma de versión de depuración utilizando montón de depuración (por defecto):

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

Hay una cabecera de la asignación, que termina con la separación, así que no hay gran probabilidad habrá 0xFDFDFDFD antes de la puntero - no es perfecto, pero puede ayudar ...

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