Seite 1 von 4

Fehler bei Str in Thread

Verfasst: 30.12.2008 04:24
von Armkrie
Dieses Programm läuft unter PB4.2 ohne Probleme.

Bei PB4.3 kommt in der Zeile 18 'SetGadgetText(#MausPosX, Str(MausPosition\x)' die Fehlermeldung 'Invalid memory access'.

Wenn man 'Str(MausPosition\x)' durch einen String ersetzt, tritt dieser Fehler nicht mehr auf.
Ich muss also davon ausgehen das der Fehler in der Str-Routine zu finden ist.

Kann mir jemand dabei Helfen ?

Code: Alles auswählen


Enumeration
  #MausPos
  #MausPosX
  #MausTrenn
  #MausPosY
EndEnumeration

Global ThreadAnzahl.b                                                ;Zähler laufender Threads
Global ThreadEnde.b                                                  ;Flag Threads beenden (1 = Ende)

Procedure Thread_MausPos(*Wert)                                      ;Thread Mausposition anzeigen
  ThreadAnzahl + 1
  Static MausPosition.POINT
  Repeat
    If ThreadEnde = 1 : Break : EndIf                                ;Thread beenden ?
    GetCursorPos_(@MausPosition.POINT)                                ;Mausposition lesen
    SetGadgetText(#MausPosX, Str(MausPosition\x))                     ;Mausposition X anzeigen
    SetGadgetText(#MausPosY, Str(MausPosition\y))                     ;Mausposition Y anzeigen
    Delay(50)
  ForEver
  ThreadAnzahl - 1
EndProcedure

If OpenWindow(0, 100, 100, 200, 40, "Test Str()")
  If CreateGadgetList(WindowID(0))                            ;##### Bei PB4.3 auskommentieren
    TextGadget(#MausPos  , 10, 10, 40, 20, "Maus:")
    TextGadget(#MausPosX , 50, 10, 35, 20, "" ,#PB_Text_Right)
    TextGadget(#MausTrenn, 85, 10, 10, 20, "/",#PB_Text_Center)
    TextGadget(#MausPosY , 95, 10, 35, 20, "")
  EndIf                                                       ;##### Bei PB4.3 auskommentieren
EndIf

CreateThread(@Thread_MausPos(), 0)                                    ;Thread starten

Repeat
  Event.l = WaitWindowEvent()
  If Event = #PB_Event_CloseWindow
    Break
  EndIf
ForEver

ThreadEnde = 1                                                        ;Threads beenden
Endezeit = ElapsedMilliseconds() + 5000                               ;Warten bis alle Threads beendet sind (max. 5 Sek.)
Repeat
  WaitWindowEvent(100)
  If ThreadAnzahl = 0 : Break : EndIf
Until ElapsedMilliseconds() > Endezeit

End


Verfasst: 30.12.2008 04:37
von edel
Als Workarround kannst du ja einfach einen String uebergeben, das scheint ja zu laufen.

Verfasst: 30.12.2008 13:57
von Armkrie
Wenn man <Str(MausPosition\x)> durch den String <"10"> ersetzt funktioniert zwar alles ohne Fehler, es wird aber nicht mehr die Mausposition angezeigt.
Wenn man immer nur einen Festwert anzeigt bringt diese Routine nicht viel. Auserdem ist das Problem mit der Str-Routine dadurch nicht gelöst.

Verfasst: 30.12.2008 14:33
von freak
Ist der Threadsafe Modus aktiviert ?

Verfasst: 30.12.2008 15:12
von roherter
freak hat geschrieben:Ist der Threadsafe Modus aktiviert ?
Habs auch nochmal getestet der Fehler tritt nur auf wenn wie Freak sagt der Threadsafe Modus aktiviert ist.

Verfasst: 30.12.2008 15:14
von cxAlex
Kann ich bestätigen. Der Fehler tritt nur auf wenn Thread-Save ein ist. Sonst läuft alles ohne Probleme

Verfasst: 30.12.2008 16:21
von Kaeru Gaman
Armkrie hat geschrieben:Wenn man <Str(MausPosition\x)> durch den String <"10"> ersetzt funktioniert zwar alles ohne Fehler, es wird aber nicht mehr die Mausposition angezeigt.
Wenn man immer nur einen Festwert anzeigt bringt diese Routine nicht viel. Auserdem ist das Problem mit der Str-Routine dadurch nicht gelöst.
da hast du wohl was falsch verstanden.

edel meinte bestimmt, du sollst das so lösen:

Code: Alles auswählen

PosX$ = Str(MausPosition\x)
  SetGadgetText(#MausPosX, PosX$ )
dass er dir nicht sinnloser weise rät, eine festen wert dort reinzuschreiben, ist doch wohl logisch.

Außerdem ist die Schlußfolgerung, es läge an der Str()-Funktion, etwas voreilig und keinesfalls zwingend.

Verfasst: 30.12.2008 16:49
von edel
Richtig, hab mich da wohl nur etwas ungluecklich ausgedrueckt.

Verfasst: 30.12.2008 19:47
von Armkrie
'Thread-sicheres Executable erstellen' ist bei mir aktiviert.
Es stimmt - wenn man diese Einstellung ausschaltet, kommt keine Fehlermeldung mehr.

Ich möchte diese Einstellung aber nicht ausschalten, weil in meinem Programm
9 Threads gleichzeitig laufen und es dann sicher an anderen Stellen Probleme gibt.

Mit der Lösung:
PosX$ = Str(MausPosition\x) : SetGadgetText(#MausPosX, PosX$)
kann man gut leben. Seltsam ist es aber trotzdem.

Habe auch noch einmal probiert:
  • TestZahlX.l = MausPosition\x
    SetGadgetText(#MausPosX, Str(TestZahlX))

    TestZahlY.s = Str(MausPosition\y)
    SetGadgetText(#MausPosY, TestZahlY)
Wenn man nur einmal bei < SetGadgetText > die STR-Funktion verwendet (siehe TestZahlX), gibt es keinen Fehler.
Wenn man bei beiden die STR-Funktion verwendet, kommt der Fehler wieder.

In irgend einer Routine muss trotzdem ein Fehler sein.

Ich möchte mich bei alle für die Lösungsvorschläge recht herzlich bedanken
und wünsche alle ein gutes neues Jahr.

:allright:

Code: Alles auswählen


Enumeration
  #MausPos
  #MausPosX
  #MausTrenn
  #MausPosY
EndEnumeration

Global ThreadAnzahl.b                                                ;Zähler laufender Threads
Global ThreadEnde.b                                                  ;Flag Threads beenden (1 = Ende)

Procedure Thread_MausPos(*Wert)                                      ;Thread Mausposition anzeigen
  ThreadAnzahl + 1
  Static MausPosition.POINT
  Repeat
    If ThreadEnde = 1 : Break : EndIf                                ;Thread beenden ?
    GetCursorPos_(@MausPosition.POINT)                                ;Mausposition lesen

    TestZahlX.l = MausPosition\x
    SetGadgetText(#MausPosX, Str(TestZahlX))

;Kein Fehler
    TestZahlY.s = Str(MausPosition\y)
    SetGadgetText(#MausPosY, TestZahlY)

;Fehler
;    TestZahlY.l = MausPosition\y
;    SetGadgetText(#MausPosY, Str(TestZahlY))

    Delay(50)
  ForEver
  ThreadAnzahl - 1
EndProcedure

If OpenWindow(0, 100, 100, 200, 40, "Test Str()")
    TextGadget(#MausPos  , 10, 10, 40, 20, "Maus:")
    TextGadget(#MausPosX , 50, 10, 35, 20, "" ,#PB_Text_Right)
    TextGadget(#MausTrenn, 85, 10, 10, 20, "/",#PB_Text_Center)
    TextGadget(#MausPosY , 95, 10, 35, 20, "")
EndIf

CreateThread(@Thread_MausPos(), 0)                                    ;Thread starten

Repeat
  Event.l = WaitWindowEvent()
  If Event = #PB_Event_CloseWindow
    Break
  EndIf
ForEver

ThreadEnde = 1                                                        ;Threads beenden
Endezeit = ElapsedMilliseconds() + 5000                               ;Warten bis alle Threads beendet sind (max. 5 Sek.)
Repeat
  WaitWindowEvent(100)
  If ThreadAnzahl = 0 : Break : EndIf
Until ElapsedMilliseconds() > Endezeit

End

Verfasst: 30.12.2008 19:58
von Kaeru Gaman
ich vermute mal das der fehler in der internen stringverwaltung verursacht wird.
also nicht direkt in Str(), auch nicht direkt in SetGadgetText(),
aber darin, wie bei ThreadSafe die ganzen Heaps im Stringpool verwaltet werden.

wenn man eine funktion wie Str() als Parameter verwendet,
muss ein temporärer Stringspeicher erzeugt werden,
der das Ergebnis von Str() auffängt und an SetGadgetText() übergibt.
das scheint nicht immer 100%ig zu funktionieren.

mit einem konkreten string, also erst das ergebnis von Str() einer Variable
zuweisen und dann an SetGadgetText übergeben, tritt das Problem nicht auf.