Seltsamer Fehler bei CallFunctionFast und Stringverkettung

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Seltsamer Fehler bei CallFunctionFast und Stringverkettung

Beitrag von Kiffi »

Hallo,

unter http://www.purebasic.fr/german/viewtopic.php?t=7263 habe ich vor
einiger Zeit einen Code vorgestellt, mit dem man rekursiv Dateien suchen
kann.

Was mir nun auffällt ist, dass der Code einen 'Invalid Memory Access'
verursacht. Ich bin mir sicher, dass dieser Fehler zum Zeitpunkt der
Veröffentlichung nicht auftrat.

Konkret knallt's in der CallFunctionFast - Zeile. Hier übergebe ich der
aufzurufenden Prozedur einen String, den ich aus 2 Strings
zusammensetze:

Code: Alles auswählen

If NotifyFunctionFindDirectory
  CallFunctionFast(NotifyFunctionFindDirectory, DirectoryToBrowse + FoundDirectoryName) ; Boing!
EndIf
Kurioserweise funktioniert es ohne Probleme, wenn ich die beiden Strings
vorher in einer 'Hilfsvariable' zusammensetze und diesen dann übergebe.

Code: Alles auswählen

If NotifyFunctionFindDirectory
  D$ = DirectoryToBrowse + FoundDirectoryName
  CallFunctionFast(NotifyFunctionFindDirectory, D$) ; Klappt!
EndIf
Kann mir jemand erklären, warum das so ist?

Danke im voraus & Grüße ... Kiffi
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Hatte das schonmal im hier und im englischen Forum gepostet.
Leider konnte ich den Workaround ueberhaupt nicht nachvollziehen,
ansonsten hat es auch keinen interessiert, also kein von 'oben' ;-) .

http://www.purebasic.fr/english/viewtopic.php?t=21722
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

Hai,

och menno! Jetzt habe ich schon wieder so'n komischen Fehler
bekommen. Ich poste das mal in diesen Thread, weil ich denke, dass der
Grund des Fehlers ähnlichen Urspungs ist.

Ich vergleiche die Grösse einer Datei mit einem von Anwender
eingegebenen Wert. Untenstehende Proc schmiert bei 'ProcedureReturn...'
mit einem 'Invalid Memory Access' ab.

Code: Alles auswählen

Procedure.l CheckFileSize(Filename$)
  If GetGadgetText(#frmMain_txtFilesizeMax) = ""
    ProcedureReturn #True
  Else
    If FileSize(Filename$) <= Val(GetGadgetText(#frmMain_txtFilesizeMax)) * 1024
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  EndIf
EndProcedure
in der nachfolgenden Prozedur hingegen wird die Anwendereingabe
lediglich in einer Hilfsvariable zwischengespeichert und siehe da: hier
funktioniert es. :?

Code: Alles auswählen

Procedure.l CheckFileSize(Filename$)
  Protected MaxLength.l
  If GetGadgetText(#frmMain_txtFilesizeMax) = ""
    ProcedureReturn #True
  Else
    MaxLength = Val(GetGadgetText(#frmMain_txtFilesizeMax)) * 1024
    If FileSize(Filename$) <= MaxLength
      ProcedureReturn #True
    Else
      ProcedureReturn #False
    EndIf
  EndIf
EndProcedure
MannMannMann, was ist da los? :|

Grüße ... Kiffi
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Das zweite ist wahrscheinlich ein Bug mit der quad-Verarbeitung - beim ersten hab ich aber kein Plan was da falsch sein könnte.
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Team100
Beiträge: 104
Registriert: 13.09.2004 22:59

Beitrag von Team100 »

Danke für das Aufzeigen des Bugs. Solche Sachen können recht
nervig sein, wenn sie in einem größeren Programm versteckt sind. .... :?

Hier mal ein kleiner Code zum Eingrenzen des Fehlers, wobei ich Kiffis Beispiel
auf das Wesentliche reduziert habe:

Code: Alles auswählen

  
Procedure test_1()  ; OK .....
    Debug "Start_1"
    If Date() > Val("34") * 1024  
      Debug "True" 
    Else
      Debug "False"
    EndIf  
    a$ = "BLABLA"
    Debug a$ 
EndProcedure

  
Procedure test_2(FileName1$, FileName2$) ; OK .....
     Debug "Start_2"
   If FileSize(FileName1$) > FileSize(FileName2$) 
     Debug "True" 
   Else
     Debug "False"
   EndIf  
     a$ = "BLABLA"
   Debug a$ 
EndProcedure
  

Procedure test_3(FileName1$)  ; OK .....
  Debug "Start_3"
  If FileSize(FileName1$) > 34 * 1024  
    Debug "True" 
  Else
    Debug "False"
  EndIf  
  a$ = "BLABLA"
  Debug a$ 
EndProcedure


Procedure test_4(FileName1$)  ; OK .....
  Debug "Start_4"
  
  wert = Val("34") * 1024
  
  If FileSize(FileName1$) > wert  
    Debug "True" 
  Else
    Debug "False"
  EndIf  
  a$ = "BLABLA"
  Debug a$ 
EndProcedure


Procedure test_5(FileName1$)  ; OK .....
  Debug "Start_5"
  If FileSize(FileName1$) > Val("34")
    Debug "True" 
  Else
    Debug "False"
  EndIf  
  a$ = "BLABLA"
  Debug a$ 
EndProcedure


Procedure test_6(FileName1$)  ;  OK .....
  Debug "Start_6"
  If FileSize(FileName1$) > ValQ("34") * 1024  
    Debug "True" 
  Else
    Debug "False"
  EndIf  
  a$ = "BLABLA"
  Debug a$ 
EndProcedure


Procedure test_7(FileName1$)  ; NOT OK .....
  Debug "Start_7"
  If FileSize(FileName1$) > Val("34") * 1024  
    Debug "True" 
  Else
    Debug "False"
  EndIf  
  a$ = "BLABLA"
  Debug a$ 
EndProcedure







  FileName1$ = GetTemporaryDirectory() + "Versuch1"
  FileName2$ = GetTemporaryDirectory() + "Versuch2"
  
  If CreateFile(100, FileName1$)
     WriteString(100, Space(100))
     CloseFile(100)
  EndIf
  
  If CreateFile(100, FileName2$)
    WriteString(100, Space(200))
    CloseFile(100)
  EndIf
   
  
  Debug "Procedure test_1"
  test_1()
  Debug "Procedure test_1 = OK"
  
  Debug "Procedure test_2"
  test_2(FileName1$, FileName2$)
  Debug "Procedure test_2 = OK"

  Debug "Procedure test_3"
  test_3(FileName1$)
  Debug "Procedure test_3 = OK"
  
  Debug "Procedure test_4"
  test_4(FileName1$)
  Debug "Procedure test_4 = OK"
  
  Debug "Procedure test_5"
  test_5(FileName1$)
  Debug "Procedure test_5 = OK"
  
  Debug "Procedure test_6"
  test_6(FileName1$)
  Debug "Procedure test_6 = OK"
  
  Debug "Procedure test_7"
  test_7(FileName1$)
  Debug "Procedure test_7 = OK"
  
  Debug "End"
  End 
Folgendes passiert:

a)
Bei test_1 gar nichts ... Date() liefert offenbar ein für den Vergleich "kompatibles" Ergebnis

b)
Bei test_2 werden zwei Ergebnisse von FileSize() verglichen ... auch ok

c)
test_3 zeigt, dass die Multiplikation beim Vergleich auch nicht stört.

d)
test_4 zeigt, wie von Kiffi erwähnt, dass eine Herausführung auf eine Variable vor dem Vergleich
auch funktioniert.

e)
test_5 zeigt, dass es an VAL() alleine auch nicht liegen kann ....

f)
test_6 läuft einwandfrei, wir konvertieren den String mit ValQ()
und stellen dieselbe Situation her wie in test_2, nämlich den
Vergleich von Quads.

g)
Bei test_7 tritt jetzt der Fehler auf. Es liegt also eindeutig an der
Kombination von FileSize() mit einer Funktionsrückgabe (hier Val() ) in
Verbindung mit der Multiplikation.

Bei der nächsten Variablenzuweisung (hier a$ = "..." ) gibt es dann Crash.
(oder bei ProcedureReturn eben ...). Läßt man die a$ Zuweisung weg,
so hängt sich das Programm bei mir kommentarlos auf.

Offensichtlich passiert beim Vergleich des Quad-Ergebnisses von
FileSize() mit dem Long-Ergebnis der Multiplikation der Speicherfehler.

Bleibt die Frage an die Entwickler, ob Vergleichsoperationen mit
unterschiedlichen Variablentypen uneingeschränkt zulässig sind.
(Wäre schon nicht schlecht .... :wink: )

Der Bug liegt also offensichtlich beim Quad-Long Vergleich unter
"erschwerten" Bedingungen (= Multiplikation von Funktionsergebnissen)

Könnte das jemand ins englische Bugforum stellen? Ich bin dort nicht
sehr präsent ... vielen Dank

Cu Team100
Kompliziert kann es jeder lösen, aber das wirklich Geniale ist einfach.....
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

@Team100:

Danke für Deine ausführliche Analyse des Problems!

> Offensichtlich passiert beim Vergleich des Quad-Ergebnisses von
> FileSize() mit dem Long-Ergebnis der Multiplikation der Speicherfehler.

... und ...

@Deeem2031:

> Das zweite ist wahrscheinlich ein Bug mit der quad-Verarbeitung

Da werdet Ihr wohl recht haben. Ein ValQ() löst das Problem.

Allerdings: Woher soll ein Normalsterblicher wissen, dass FileSize() ein
Quad zurückliefert? In der Hilfe steht sowas nicht.

Grüße .... Kiffi
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Kiffi hat geschrieben:@Deeem2031:

> Das zweite ist wahrscheinlich ein Bug mit der quad-Verarbeitung

Da werdet Ihr wohl recht haben. Ein ValQ() löst das Problem.

Allerdings: Woher soll ein Normalsterblicher wissen, dass FileSize() ein
Quad zurückliefert? In der Hilfe steht sowas nicht.

Grüße .... Kiffi
Sowas weiß man, schließlich gabs schon genug Fehler mit FileSize() :wink:
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
Andre
PureBasic Team
Beiträge: 1765
Registriert: 11.09.2004 16:35
Computerausstattung: MacBook Core2Duo mit MacOS 10.6.8
Lenovo Y50 i7 mit Windows 10
Wohnort: Saxony / Deutscheinsiedel
Kontaktdaten:

Beitrag von Andre »

Kiffi hat geschrieben: Da werdet Ihr wohl recht haben. Ein ValQ() löst das Problem.

Allerdings: Woher soll ein Normalsterblicher wissen, dass FileSize() ein
Quad zurückliefert? In der Hilfe steht sowas nicht.
Könnte man aber ändern... :wink:

Jetzt, wo ich dies dann auch weiß.
Bye,
...André
(PureBasicTeam::Docs - PureArea.net | Bestellen:: PureBasic | PureVisionXP)
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Könnte man aber ändern... :wink:

ja das wäre super! :allright:

Allerdings wäre es auch nicht gerade verkehrt, wenn PB selber darauf
hinweisen würde, dass Vergleichswerte datentyptechnisch nicht zueinander
passen.

Danke & Grüße ... Kiffi
Antworten