Fehler bei Str in Thread

Hier werden, insbesondere in den Beta-Phasen, Bugmeldungen gepostet. Das offizielle BugForum ist allerdings hier.
Armkrie
Beiträge: 17
Registriert: 30.12.2008 04:03

Fehler bei Str in Thread

Beitrag 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

Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Als Workarround kannst du ja einfach einen String uebergeben, das scheint ja zu laufen.
Armkrie
Beiträge: 17
Registriert: 30.12.2008 04:03

Beitrag 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.
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Beitrag von freak »

Ist der Threadsafe Modus aktiviert ?
Benutzeravatar
roherter
Beiträge: 1407
Registriert: 10.04.2005 18:58
Kontaktdaten:

Beitrag 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.
Purebasic 5.0 32bit und 64 bit

I'm back from hell
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Kann ich bestätigen. Der Fehler tritt nur auf wenn Thread-Save ein ist. Sonst läuft alles ohne Probleme
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Richtig, hab mich da wohl nur etwas ungluecklich ausgedrueckt.
Armkrie
Beiträge: 17
Registriert: 30.12.2008 04:03

Beitrag 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
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten