Zum Beispiel:
void func1(){
int i = 123;
func2(&i);
}
void func2(int *a){
*a = 456;
}
Wann func1
Berufung func2
wird ein Zeiger auf eine lokale Variable übergeben func2
— der Zeiger zeigt auf den Stack. Ist das sicher für die Regeln von C?
Vielen Dank.
Der Umfang der i
ist func1
und es überdauert den Aufruf an func2
. Es ist also absolut sicher.
Wie in den meisten Antworten zuvor erwähnt, ist es absolut sicher, den Zeiger an zu übergeben func2()
in deinem Spezialfall.
In einer realen Software halte ich dies jedoch für schädlich, da Sie keine Kontrolle darüber haben, was func2()
macht mit Ihrer Variablen. func2()
kann einen Alias für seinen Parameter erstellen, um ihn zu einem späteren Zeitpunkt asynchron zu verwenden. Und zu diesem Zeitpunkt die lokale Variable int i
kann weg sein, wenn dieser Alias später verwendet wird.
Aus meiner Sicht ist das Übergeben eines Zeigers auf eine lokale (automatische) Variable äußerst gefährlich und sollte vermieden werden.
Sie können dies tun, wenn Sie die Variable in deklarieren func1()
wie static int i;
Dabei ist sichergestellt, dass der Speicher z i
werden nicht recycelt und überschrieben. Sie müssen jedoch einige Mutex-Sperren für die Zugriffskontrolle auf diesen Speicher in einer gleichzeitigen Umgebung einrichten.
Um dieses Problem zu veranschaulichen, hier ein Code, über den ich gerade gestern gestolpert bin, als ich Softwaretests bei meinem Kunden durchführte. Und ja, es stürzt ab…
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;
}
In diesem Fall werden die Daten in der DataBuff
ist längst weg, wenn der Zeiger drin ist ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr
wird verwendet, um die Daten im EEPROM zu speichern.
Um diesen Code zu beheben, muss er zumindest deklariert werden static UINT8 DataBuff[25];
Darüber hinaus gilt es als auch zu deklarieren static valueObj_t NVMemObj
da wir nicht wissen, was die aufgerufene Funktion mit diesem Zeiger macht.
Um es kurz zu sagen:
TL;DR
Obwohl es in der C-Sprache legal ist, halte ich es für schädlich, Zeiger auf automatische Variablen in einem Funktionsaufruf zu übergeben. Man weiß nie (und will es oft auch nicht wissen), was genau die aufgerufene Funktion mit den übergebenen Werten macht. Wenn die aufgerufene Funktion einen Alias erstellt, bekommen Sie große Probleme.
Nur meine 2 Cent.
Ja, es ist sicher, einen Zeiger auf eine lokale Variable zu übergeben, aber Sie können keinen Zeiger auf eine automatische lokale Variable von einer Funktion zurückgeben.
Ja, Ihr Code ist sicher.
Solange die Lebensdauer des Objekts noch nicht abgelaufen ist, ist es sicher, lokale Variablen so zu übergeben, wie Sie es tun.
Ist das sicher für die Regeln von C?
Was Sie tun, ist sicher, da die lokale Variable immer noch gültig ist und sich im Gültigkeitsbereich befindet. Der Zugriff auf die lokale Variable außerhalb ihres Gültigkeitsbereichs ist ein undefiniertes Verhalten, aber das ist völlig in Ordnung
In Ihrem Fall können Sie sicher verwenden &i
bis zu der zeit i
ist gültig.
Nun, wie wir sehen können i
hat ein Leben bis zum Ende func1()
. Als die func2()
wird von der angerufen func1()
und die func1()
hat die Ausführung noch nicht beendet, also i
Ist noch gültig.
Aus diesem Grund wird normalerweise die Adresse einer lokalen Variablen an eine andere Funktion übergeben normalerweise zulässig (die Lebensdauer der Variablen ist noch nicht abgelaufen), aber return
die Adresse einer lokalen Variablen (unmittelbar nach return
lokale Variablen der Funktion entfallen) ist nicht erlaubt.
TL;DR :Sie können sicher verwenden &i
als Argument von func2()
wie hier gezeigt.
Die Verwendung eines Zeigers auf eine Variable, nachdem die Variable zerstört wurde, ist unsicher. Das machst du hier nicht.
– Benutzer253751
17. Februar 2015 um 8:09 Uhr
Mögliches Duplikat von Safe to pass pointer to auto variable to function?
– Ravron
10. Februar 2016 um 20:22 Uhr