Zeiger an lokale Variable übergeben, um zu funktionieren: Ist es sicher?

Lesezeit: 4 Minuten

Benutzer-Avatar
Albert Zhang

Zum Beispiel:

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

Wann func1 Berufung func2wird 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.

  • 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

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 NVMemObjda 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.

  • “func2() kann einen Alias ​​für seinen Parameter erstellen, um ihn zu einem späteren Zeitpunkt asynchron zu verwenden”. Dasselbe könnte jedoch über mallocated Memory gesagt werden, das Sie an eine Funktion übergeben … es könnte einen Alias ​​​​für ihn erstellen, auf den es versucht zuzugreifen, nachdem der Aufrufer den Speicher später freigegeben hat. Es geht hier nicht darum, dass der Anrufer etwas falsch macht, sondern das genannte Funktion Verweise (wo? in einer globalen?) auf seine eigenen Argumente beibehalten, in denen es wiederverwendet wird spätere Anrufe. Bedenken Sie auch, dass dies ein sicherer Ausgangspunkt ist, da sie nicht befreit werden müssen. TLDR; automatische Variablen=gut. Funktionen, die Zeiger auf ihre args=bad halten.

    – aaa90210

    5. April 2017 um 23:12 Uhr

  • @ aaa90210 Aber das Beispiel verwendet keinen Malloc-Speicher. Es verwendet a static Puffer, der während der gesamten Lebensdauer des Prozesses garantiert vorhanden ist. Also stimme ich zu, malloc oder C++ new sind gefährlich. Aber statisch mit Mutexe ist es nicht.

    – deLock

    15. Januar 2020 um 16:47 Uhr


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 returndie Adresse einer lokalen Variablen (unmittelbar nach returnlokale Variablen der Funktion entfallen) ist nicht erlaubt.

TL;DR :Sie können sicher verwenden &i als Argument von func2() wie hier gezeigt.

1300780cookie-checkZeiger an lokale Variable übergeben, um zu funktionieren: Ist es sicher?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy