Aktuelle Zeit: 20.10.2019 16:11

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: (Pointer) Nie Pointer zu lokalen Variablen zurückgeben!
BeitragVerfasst: 22.05.2005 17:18 
Offline
Ein Admin
Benutzeravatar

Registriert: 29.08.2004 20:20
Wohnort: Saarbrücken
Ich habe das letztens in einem Code von Deeem2031 entdeckt. Er hat Pointer zu lokalen Variablen einer Procedure zurückgegeben, was in vielen Fällen zunächst mal kein Problem darstellt, wie man hier sieht:
Code:
Procedure.l pGetValue()
  Protected a.l
  a = 123
  ProcedureReturn @a
EndProcedure
*a.LONG = pGetValue()
Debug *a\l
Fügt man jetzt allerdings noch eine Zeile an, die neuen Speicher allokiert, sieht es so aus:
Code:
Procedure.l pGetValue()
  Protected a.l
  a = 123
  ProcedureReturn @a
EndProcedure
*a.LONG = pGetValue()
Debug *a\l
Dim b.l(1)
Debug *a\l
Man könnte jetzt natürlich direkt den Wert der Procedure mit [c]PeekL()[/c] auslesen und in eine globale Variable lesen, was zunächst funktioniert:
Code:
Procedure.l pGetValue()
  Protected a.l
  a = 123
  ProcedureReturn @a
EndProcedure
a.l = PeekL(pGetValue())
Debug a
Dim b.l(1)
Debug a
Aber in Zusammenhang mit Threads kann es durchaus passieren, dass in dieser einen Zeile, die ja trotzdem noch aus mehreren ASM-Befehlen besteht, die Speicherstelle, der die lokale Variable zugeordnet war, geändert wird, bevor [c]PeekL()[/c] den Wert ausgelesen und zurückgegeben hat.
Leider lässt sich dafür kein Code erfinden, der nach wenigen Sekunden Laufzeit direkt Fehler ausgibt. Aber im Grunde würde das dann so aussehen:
Code:
Procedure Thread(a.l)
  Repeat
    Dim b.l(Random(10))
  ForEver
EndProcedure

Procedure.l pGetValue()
  Protected a.l
  a = 123
  ProcedureReturn @a
EndProcedure

hT.l = CreateThread(@Thread(), 0)

For a.l = 1 To 1000
  a.l = PeekL(pGetValue())
  If a <> 123 : Debug a : EndIf
Next

KillThread(hT)

_________________
Neustes Video: Neje DK - 1 Watt Laser Engraver
Ubuntu Gnome 19.04 LTS x64, PureBasic 5.71 x64 (außerdem 4.41, 4.50, 4.61, 5.00, 5.10, 5.11, 5.21, 5.22, 5.30, 5.31, 5.40, 5.50, 5.60)
"Die deutsche Rechtschreibung ist Freeware, du darfst sie kostenlos nutzen – Aber sie ist nicht Open Source, d. h. du darfst sie nicht verändern oder in veränderter Form veröffentlichen."


Zuletzt geändert von NicTheQuick am 23.05.2005 15:41, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 23.05.2005 08:51 
Offline
Benutzeravatar

Registriert: 08.09.2004 08:53
Wenn man Variablen-Inhalte aus einer Procedure verwenden möchte,
muss man diese mit Static deklarieren, sonst wird dieser Speicherplatz
natürlich wieder freigegeben ...

Code:
Procedure.l pGetValue()
  Static a.l
  a = 123
  ProcedureReturn @a
EndProcedure
*a.LONG = pGetValue()
Debug *a\l
Dim b.l(1)
Debug *a\l

_________________
"Papa, mein Wecker funktioniert nicht! Der weckert immer zu früh."


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 23.05.2005 14:44 
Offline
Benutzeravatar

Registriert: 29.08.2004 01:37
Ist doch eigentlich allgemein bekannt, oder nicht? Ich meine, in C ist es genauso, dass Variablen nur innerhalb des Scopes gültig sind, also nur innerhalb des Blocks der geschweiften Klammern. Und in Funktionen gilt dies auch, dass die Variablen eben danach wieder freigegeben werden. Demnach sollte man keine Pointer auf lokale Variablen legen, wenn man diese Pointer nicht danach auch wieder NULL setzt.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 23.05.2005 15:24 
Offline
Ein Admin
Benutzeravatar

Registriert: 29.08.2004 20:20
Wohnort: Saarbrücken
Klar ist das klar. Aber anscheinend nicht jedem. Und den Anfängern sicherlich erstmal gar nicht. (Wobei die wahrscheinlich eher weniger mit Pointern arbeiten).

@dige: Deine Version ist jetzt zwar kein illegaler Speicherzugriff mehr, der in meinem Beispiel nur zufällig funktioniert, aber verwenden darf man diese Methode nur dann, wenn die Funktion nicht noch von anderen Threads verwendet wird, weil dort dann diese Static-Variable auch wieder verändert werden kann.

Wesentlich sicherer und eleganter ist dafür die folgende Methode:
Code:
Procedure.l pGetValue(*get.LONG)
  Protected a.l
  a = 123
  If *get
    *get\l = a
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

a.l
pGetValue(@a)
Debug a

_________________
Neustes Video: Neje DK - 1 Watt Laser Engraver
Ubuntu Gnome 19.04 LTS x64, PureBasic 5.71 x64 (außerdem 4.41, 4.50, 4.61, 5.00, 5.10, 5.11, 5.21, 5.22, 5.30, 5.31, 5.40, 5.50, 5.60)
"Die deutsche Rechtschreibung ist Freeware, du darfst sie kostenlos nutzen – Aber sie ist nicht Open Source, d. h. du darfst sie nicht verändern oder in veränderter Form veröffentlichen."


Zuletzt geändert von NicTheQuick am 23.05.2005 15:43, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 4 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  
cron

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye