Zeiger auf lokale Variable übergeben, um zu funktionieren: ist es sicher?

8

Zum Beispiel:

%Vor%

Wenn func1 aufrufende func2 , wird ein Zeiger auf lokale Variable an func2 übergeben - der Zeiger wird auf den Stapel gerichtet. Ist das sicher für die Regeln von C?

Danke.

    
Albert Zhang 17.02.2015, 07:48
quelle

6 Antworten

14

Der Bereich von i ist func1 und überlebt den Aufruf von func2 . So ist es vollkommen sicher.

    
juanchopanza 17.02.2015, 07:50
quelle
3

Wie in den meisten Antworten bereits erwähnt, ist es absolut sicher, den Zeiger in Ihrem Sonderfall an func2() zu übergeben.

In einer realen Software betrachte ich dies jedoch als schädlich, da Sie nicht kontrollieren können, was func2() mit Ihrer Variablen macht. func2() kann einen Alias ​​für seinen Parameter erstellen, um ihn zu einem späteren Zeitpunkt asynchron zu verwenden. Und zu diesem Zeitpunkt kann die lokale Variable int i weg sein, wenn dieser Alias ​​später verwendet wird.

Aus meiner Sicht ist das Übergeben eines Zeigers an eine lokale (automatische) Variable äußerst gefährlich und sollte vermieden werden.

Sie können dies tun, wenn Sie die Variable in func1() als static int i;

deklarieren

In diesem Fall wird sichergestellt, dass der Speicher für i nicht wiederverwendet und überschrieben wird. Sie müssen jedoch einige Mutex-Sperren für die Zugriffssteuerung auf diesen Speicher in einer gleichzeitigen Umgebung einrichten.

Um dieses Problem zu illustrieren, ist hier ein Code, über den ich gestern beim Testen von Software bei meinem Kunden gestolpert bin. Und ja, es stürzt ab ...

%Vor%

In diesem Fall sind die Daten in DataBuff lange weg, wenn der Zeiger in ASyncQueue.CommandArray[ASyncQueue.NextFreeEntry].BufferPtr zum Speichern der Daten im EEPROM verwendet wird.

Um diesen Code zu beheben, muss mindestens static UINT8 DataBuff[25]; deklariert werden. Außerdem sollte auch static valueObj_t NVMemObj deklariert werden, 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 erlaubt ist, halte ich es für schädlich, Zeiger auf automatische Variablen in einem Funktionsaufruf zu übergeben. Sie wissen nie (und oft wollen Sie nicht wissen), was genau die aufgerufene Funktion mit den übergebenen Werten macht. Wenn die aufgerufene Funktion einen Alias ​​festlegt, gerät man in große Schwierigkeiten.

Nur meine 2 Cent.

    
opt12 10.02.2016 07:56
quelle
2
___ qstntxt ___

Zum Beispiel:

%Vor%

Wenn %code% aufrufende %code% , wird ein Zeiger auf lokale Variable an %code% übergeben - der Zeiger wird auf den Stapel gerichtet. Ist das sicher für die Regeln von C?

Danke.

    
___ answer35309620 ___

Wie in den meisten Antworten bereits erwähnt, ist es absolut sicher, den Zeiger in Ihrem Sonderfall an %code% zu übergeben.

In einer realen Software betrachte ich dies jedoch als schädlich, da Sie nicht kontrollieren können, was %code% mit Ihrer Variablen macht. %code% kann einen Alias ​​für seinen Parameter erstellen, um ihn zu einem späteren Zeitpunkt asynchron zu verwenden. Und zu diesem Zeitpunkt kann die lokale Variable %code% weg sein, wenn dieser Alias ​​später verwendet wird.

Aus meiner Sicht ist das Übergeben eines Zeigers an eine lokale (automatische) Variable äußerst gefährlich und sollte vermieden werden.

Sie können dies tun, wenn Sie die Variable in %code% als %code%

deklarieren

In diesem Fall wird sichergestellt, dass der Speicher für %code% nicht wiederverwendet und überschrieben wird. Sie müssen jedoch einige Mutex-Sperren für die Zugriffssteuerung auf diesen Speicher in einer gleichzeitigen Umgebung einrichten.

Um dieses Problem zu illustrieren, ist hier ein Code, über den ich gestern beim Testen von Software bei meinem Kunden gestolpert bin. Und ja, es stürzt ab ...

%Vor%

In diesem Fall sind die Daten in %code% lange weg, wenn der Zeiger in %code% zum Speichern der Daten im EEPROM verwendet wird.

Um diesen Code zu beheben, muss mindestens %code% deklariert werden. Außerdem sollte auch %code% deklariert werden, 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 erlaubt ist, halte ich es für schädlich, Zeiger auf automatische Variablen in einem Funktionsaufruf zu übergeben. Sie wissen nie (und oft wollen Sie nicht wissen), was genau die aufgerufene Funktion mit den übergebenen Werten macht. Wenn die aufgerufene Funktion einen Alias ​​festlegt, gerät man in große Schwierigkeiten.

Nur meine 2 Cent.

    
___ answer28557067 ___

Ja, Ihr Code ist sicher.

Solange die Lebensdauer des Objekts noch nicht abgelaufen ist, können lokale Variablen wie Sie sicher übergeben werden.

    
___ answer28557068 ___

Der Bereich von %code% ist %code% und überlebt den Aufruf von %code% . So ist es vollkommen sicher.

    
___ answer28557074 ___
  

Ist das sicher für die Regeln von C?

Was Sie tun, ist sicher, da die lokale Variable immer noch gültig ist und innerhalb des Gültigkeitsbereichs liegt. Zugriff auf die lokale Variable außerhalb ihres Gültigkeitsbereichs ist undefined Behavior, aber das ist völlig in Ordnung

    
___ tag123pointer ___ Datentyp, der auf einen anderen gespeicherten Wert zeigt. Eine Zeigervariable enthält eine Speicheradresse einer anderen Entität (Variable oder Funktion oder andere Entität). Dieses Tag sollte für Fragen verwendet werden, bei denen Zeiger und keine Referenzen verwendet werden. Die gebräuchlichsten Programmiersprachen, die Zeiger verwenden, sind C-, C ++ -, Go- und Assemblersprachen. Verwenden Sie ein bestimmtes Sprach-Tag. Andere hilfreiche Tags sind Methode, Funktion, Struktur usw., die die Verwendung von Pointer beschreiben. ___ answer28557123 ___

In Ihrem Fall können Sie sicher %code% verwenden, bis die Zeit %code% gültig ist.

Nun, wie wir sehen können, hat %code% eine Lebensdauer bis zum Ende von %code% . Da der %code% von %code% aufgerufen wird und der %code% die Ausführung noch nicht beendet hat, ist %code% immer noch gültig.

Aus diesem Grund ist es normalerweise normalerweise erlaubt, die Adresse einer lokalen Variablen an eine andere Funktion zu übergeben (die Lebensdauer der Variablen ist nicht abgelaufen), aber die Adresse einer lokalen Variablen (unmittelbar danach) %code% , lokale Variablen der Funktion existieren nicht mehr) ist nicht erlaubt.

TL; DR : Sie können sicher %code% als Argument von %code% verwenden, wie hier gezeigt.

    
___ tag123stack ___ Ein Stapel ist ein LIFO-abstrakter Datentyp und eine letzte Datenstruktur. Eine häufige Verwendung von Stapeln besteht darin, Unterroutinenargumente zu speichern und Adressen zurückzugeben. ___ tag123c ___ C ist eine universelle Computerprogrammiersprache, die für Betriebssysteme, Bibliotheken, Spiele und andere Hochleistungsanwendungen verwendet wird. Dieses Tag sollte bei allgemeinen Fragen zur C-Sprache verwendet werden, wie in der Norm ISO 9899: 2011 definiert. Fügen Sie ggf. ein versionsspezifisches Tag wie c99 oder c90 für Fragen zu älteren Sprachstandards hinzu. C unterscheidet sich von C ++ und es sollte nicht mit dem C ++ - Tag kombiniert werden, wenn ein rationaler Grund fehlt. ___ qstnhdr ___ Zeiger auf lokale Variable übergeben, um zu funktionieren: ist es sicher? ___
haccks 17.02.2015 07:50
quelle
1

Ja, Ihr Code ist sicher.

Solange die Lebensdauer des Objekts noch nicht abgelaufen ist, können lokale Variablen wie Sie sicher übergeben werden.

    
P.P. 17.02.2015 07:50
quelle
1
  

Ist das sicher für die Regeln von C?

Was Sie tun, ist sicher, da die lokale Variable immer noch gültig ist und innerhalb des Gültigkeitsbereichs liegt. Zugriff auf die lokale Variable außerhalb ihres Gültigkeitsbereichs ist undefined Behavior, aber das ist völlig in Ordnung

    
Gopi 17.02.2015 07:50
quelle
1

In Ihrem Fall können Sie sicher &i verwenden, bis die Zeit i gültig ist.

Nun, wie wir sehen können, hat i eine Lebensdauer bis zum Ende von func1() . Da der func2() von func1() aufgerufen wird und der func1() die Ausführung noch nicht beendet hat, ist i immer noch gültig.

Aus diesem Grund ist es normalerweise normalerweise erlaubt, die Adresse einer lokalen Variablen an eine andere Funktion zu übergeben (die Lebensdauer der Variablen ist nicht abgelaufen), aber die Adresse einer lokalen Variablen (unmittelbar danach) return , lokale Variablen der Funktion existieren nicht mehr) ist nicht erlaubt.

TL; DR : Sie können sicher return als Argument von &i verwenden, wie hier gezeigt.

    
Sourav Ghosh 17.02.2015 07:53
quelle

Tags und Links