Pasar el puntero a la variable local para funcionar: ¿es seguro?

Por ejemplo:

void func1(){ int i = 123; func2(&i); } void func2(int *a){ *a = 456; } 

Cuando func1 llama a func2 , se func2 un puntero a la variable local a func2 : el puntero se señala a la stack. ¿Es esto seguro para las reglas de C?

Gracias.

El scope de i es func1 y sobrevive a la llamada a func2 . Así que es perfectamente seguro.

Como se indica en la mayoría de las respuestas anteriores, es perfectamente seguro pasar el puntero a func2() en su caso especial.

Sin embargo, en una pieza de software del mundo real, considero que esto es perjudicial ya que no tienes control sobre qué está haciendo func2() con tu variable. func2() puede crear un alias para su parámetro para usarlo de forma asincrónica en un momento posterior. Y en ese momento, la variable local int i puede desaparecer cuando este alias se use más adelante.

Entonces, desde mi punto de vista, pasar un puntero a una variable local (automática) es extremadamente peligroso y debe evitarse.

Puede hacerlo si declara la variable en func1() como static int i;

En ese caso, se garantiza que la memoria no se reciclará ni se sobrescribirá. Sin embargo, deberá configurar algún locking Mutex para el control de acceso a esta memoria en un entorno concurrente.

Para ilustrar este problema, aquí hay un código con el que me topé ayer mientras hacía pruebas de software a mi cliente. Y sí, se estrella …

 void func1() { // Data structure for NVMemory calls valueObj_t NVMemObj; // a data buffer for eeprom write UINT8 DataBuff[25]; // [..] /* Assign the data pointer to NV Memory object */ NVMemObj.record = &DataBuff[0]; // [..] // Write parameter to EEPROM. (void)SetObject_ASync(para1, para2, para3, &NVMemObj); return; } void SetObject_ASync(para1, para2, para3, valueObj_t *MemoryRef) { //[..] ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr = MemoryRef->record; //[..] return; } 

En este caso, los datos en el DataBuff desaparecido cuando el puntero en ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr se utiliza para almacenar los datos en la EEPROM.

Para corregir este código, al menos es necesario declarar static UINT8 DataBuff[25]; Además, se considerará que también se declara static valueObj_t NVMemObj ya que no sabemos qué está haciendo la función llamada con ese puntero.

Para decirlo brevemente: TL; DR

A pesar de que es legal en el lenguaje C, considero que es perjudicial pasar punteros a variables automáticas en una llamada de función. Nunca se sabe (y con frecuencia no se quiere saber) qué hace exactamente la función llamada con los valores pasados. Cuando la función llamada establece un alias, te metes en grandes problemas.

Sólo mis 2 centavos.

Sí, es seguro pasar un puntero a una variable local, pero no puede devolver un puntero a una variable local automática desde una función.

Sí, tu código es seguro.

Mientras la vida útil del objeto no haya terminado, es seguro pasar las variables locales como lo hace usted.

¿Es esto seguro para las reglas de C?

Lo que está haciendo es seguro ya que la variable local sigue siendo válida y está dentro del scope. Acceder a lo local fuera de su scope es un comportamiento indefinido, pero esto es totalmente correcto.

En su caso, puede usar de forma segura &i hasta el momento en que sea válido.

Ahora, como podemos ver, func1() una vida útil hasta el final de func1() . Como se llama a func1() desde func1() y func1() aún no ha finalizado su ejecución, entonces, i sigue siendo válido.

Por eso, generalmente se permite pasar la dirección de una variable local a otra función (la vida útil de la variable no ha terminado), pero return la dirección de una variable local (inmediatamente después del return , las variables locales de la función dejan de existir) es no permitido

TL; DR : Puede usar &i seguridad como el argumento de func2() como se muestra aquí.