Probleme mit TP 7 - Seltsames Verhalten der Programme

Diskussion zum Thema Programmierung unter DOS (Intel x86)
Brueggi

Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Hallo DOS-Fans,

ich habe bei einem aktuellen Projekt ziemliche Schwierigkeiten mit TP. Ich schreibe gerade einen neuen Desktop für GOS. Weil mir ASM zu aufwendig ist, habe ich zu TP gegriffen, da sich so ein Code besser warten und erweitern lässt - dachte ich. Nun, hätte ich gedacht, dass es solche Probleme gibt, hätte ich es gelassen...

Bisher lief alles glatt - bis dann plötzlich (ich habe eine Procedure eingefügt, die BDOS-Programme ausführt) keine Icons am Desktop mehr angezeigt wurden bzw. die Daten der Icons verstümmelt waren (z. B. statt "CMD.APL" als verknüpfte Anwendung stand "CM<ascii-schrott>". Ich habe mir da schon 3h einen Wolf gesucht - aber der betroffene Code war und ist i.O. - daran wurde nichts geändert.

Ich habe dann eine kleine Debug-Procedure erstellt, die einfach mal alle Array-Einträge in einer AlertBox ausgibt. Alleine das HInzufügen der Procedure hat offenbar gereicht - denn jetzt hat wieder alles funktioniert (komisch komisch). Nun, vorgestern habe ich alles auf herz und nieren getestet und keine Fehler gefunden. Also habe ich gestern die Hintergrund-Bild-Funktionen eingebaut.

Dabei kommt eine eigene Unit mit dem Namen BMP zum Einsatz. Sie liest ein BMP-Bild in einen Puffer (wird mit GetMem angefordert) und zeigt aus diesem heraus das Bild an (Zielsegment $A000). Die Unit hat bisher keine Probleme bereitet - nur jetzt. Sobald auch nur eine Procedure der Unit BMP im Desktop verwendet wird, verhält sich das Programm wieder seltsam. Piktogramme erhalten nur das Default-Icon, angeblich können keine Anwendungen mehr gestartet werden, da der Pfad ungültig ist (was er nicht ist). Wählt man ein Hintergrundbild, dann sind ggf. nur ein teil der Icons sichtbar... selbst wenn ich in USES die Reihenfolge von GOS286, BGOS286, BMP; auf BMP, BGOS286, GOS286; ändere, funktioniert Code, der vorher abgestürzt ist, dafür wieder andere Teile nicht. Sobald ich die Unit BMP rausnehme, läufts.

Füge ich die Proceduren aus BMP direkt in den Desktop-Code ein (ohne diese zu benutzen), stürzt irgendein Programmteil ab, der vorher funktioniert hat.

Ich habe schon Range-Check und sämtliche Compiler-Switches probiert - TPC sagt, alles ist ok (kann mir auch nur schwer vorstellen, dass 29K Code und 16K Daten ein Problem wären...). Da mich diese Fehler langsam extrem nerven und ich wirklich keine Lust habe, nach 3-4h der Suche dann wieder dort zu stehen, wo man zu Beginn des Tages war, wende ich mich an Euch. Was kann ich noch probieren?

Das seltsame ist: Wenn ich in der Unit BMP statt

UNIT BMP;

INTERFACE

USES BGOS286;

procedure ......

das USES BGOS286; nach IMPLEMENTATION setze, dann funktionieren im Desktop wieder ganz andere Dinge nicht mehr, die vorher gelaufen sind.... Ich bin mit meinem Latein am Ende. Sehe ich das richtig, dass Units, die innerhalb einer Unit verwendet werden, nur "lokal" verfügbar sind, wenn sie bei Implementation stehen?

Was ich definitiv ausschließen kann ist das, dass Daten irgendwo den Code überschreiben. Die Routinen aus BMP sind in anderen Programmen auch im Einsatz. Die Units GOS286 und BGOS286 sind schon bei einem Dutzend Programme in Gebrauch - diese Programme laufen anstandslos. Weiss einer von Euch Rat?

Viele Grüße,

Brueggi
Benutzeravatar
Dosenware
DOS-Gott
Beiträge: 3745
Registriert: Mi 24. Mai 2006, 20:29

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Dosenware »

" wenn sie bei Implementation stehen?"

jepp, Units die im Interfaceteil angegeben werden, werden über das Iterface für alle nutzbar.

Also wenn Programm C unit B nutzt und diese wiederrum Unit A - dann hängt es von Unit B ab, ob Programm C auf Unit A zugreifen kann, oder nicht: USES im Interface -> Vollzugriff von C auf A; USES bei Implementation -> kein direkter Zugriff von C auf A.

BTW. verwendest du bei deinen Units den Initialisierungsteil? Evtl. kommt sich da etwas in die Quere.
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Hallo, danke für die Meldung. Einen Initialisierungsteil nutzt keine Unit, da dies nicht notwendig ist.
wobo
DOS-Guru
Beiträge: 614
Registriert: So 17. Okt 2010, 14:40

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von wobo »

Brueggi hat geschrieben: .... Ich habe mir da schon 3h einen Wolf gesucht - aber der betroffene Code war und ist i.O. -
Das ist bei mir normal. Letzthin habe ich zwei Tage nach dem Fehler gesucht und wollte schon TP verteufeln. Irgendwann ist mir aufgefallen, dass ich beim Aufruf einer Procedure die Reihenfolge zweier Parameter verwechselt hatte, was die seltsamsten Ergebnisse verursacht hatte. Den Fehler hatte ich anfangs nicht entdeckt, obwohl ich bestimmt 20 Mal über die Zeilen drüber gegangen bin.

Alle meine Fehler, die ich in meiner bisherigen Programmierzeit hatte, waren alles meine. TP war niemals schuld, auch wenn meine erste Schuldzuweisung meistens an TP ging...

Deine Fehlerbeschreibung kann ja alles mögliche als Fehler zu lassen. Tippen würde ich auf zerschossenen Heap, weil das bei meinen obskuren Fehlern, die sich anfangs nicht lokalisieren liessen, meist der Fall war.

Gibt man z.B. allozierten Speicher über FreeMem( MyPtr, MySize); wieder frei, zeigt MyPtr nachwie vor auf den ursprünglichen Speicherbereich. Nur der Pascal-Heap-Manager verwendet den Speicher dann für die nächste Heap-Allokation.

Mir ist es schon öfters passiert, dass ich z.B. innerhalb einer Procedure zuerst Speicher allokiert habe, diesen verarbeitet habe und dann am Ende mittels FreeMem freigegeben habe. Wochen später will ich weitere Funktionen einbauen und übersehe das FreeMem. Alles klappt trotzdem, weil der Pointer ja noch auf den ursprünglichen, jetzt aber ungültigen Speicherbereich zeigt. Irgendwann später kommt es dann zu unerklärlichen Fehlern...

Deswegen setze ich nach FreeMem,Dispose etc. den Pointer immer explizit auf NIL. Dann gibt es immer gleich beim ersten Zugriff einen Absturz und ich finde den Fehler schneller...

Ansonsten noch hatte es einmal bei mir geholfen, den Stack von 16kb auf 32kb zu erhöhen, obwohl trotz $+ kein Stack warning erfolgte.
Brueggi hat geschrieben: Was ich definitiv ausschließen kann ist das, dass Daten irgendwo den Code überschreiben. Die Routinen aus BMP sind in anderen Programmen auch im Einsatz. Die Units GOS286 und BGOS286 sind schon bei einem Dutzend Programme in Gebrauch - diese Programme laufen anstandslos. Weiss einer von Euch Rat?

Viele Grüße,

Brueggi
Würde ich auch ausschließen, dass Daten den Code überschreiben. Meistens ist es der Code, der Daten oder Code überschreibt. Zumindest meine Daten sind immer recht passiv ;-))
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Huhu, danke für die Rückmeldung :-)

Ich habe gestern nach meiner Spätschicht nochmal alles geprüft - ob wirklich die Deklarationen stimmen, habe mir die Procedure-Header aus den Units in das Hauptprogramm kopiert und mit dem Aufrufer verglichen, habe geprüft, ob Vars irgendwo doppelt geprüft werden, habe GetMem/FreeMem verglichen - ich werd nicht schlau draus - alles korrekt.

Nachdem ich dann einfach mal weiter programmiert habe und den Farbdialog eingebaut habe, musste ich feststellen, dass wieder alles funktioniert hat. Aber nur solange, bis ich einen Text nicht mehr an X 24, sondern an X 56 ausgegeben habe - danach ging plötzlich die Menüabfrage nicht mehr..... Ich habe dann das selbe Programm direkt auf dem P1 geladen - es hat funktioniert. Ok, nach 1/2h war auch da schluss. Ich kenne ja so ein komisches Verhalten von TP, wenn man z. B.

Procedure blabla(xxx: irgendeintyp);
begin
xxx:=<irgendeinwert>
end;

schreibt, dann bröselt der Rechner auch vor sich hin und es kommen scheinbar zufällige Fehler. Nur, das ist nicht der Fall. Das einzige, was ich jetzt noch machen kann ist das, ich nehme alle Vars aus den Procedures im Hauptprogramm und deklariere diese global, nicht mehr lokal. Und dann mal schauen, was passiert.

Ansonsten bin ich immer noch ratlos - da eben jedes mal ein anderer Programmteil nicht funktioniert. Wozu ich dann Range-/Stack- und Gedönse-Checking hab, wenn doch nichts geprüft wird... Also bisher kann ich nur sagen, in meinen paar Tausend Zeilen BDOS-Source (Assembler) habe ich Fehler definitiv IMMER schneller gefunden, als in TP. Und das heißt was :-)
wobo
DOS-Guru
Beiträge: 614
Registriert: So 17. Okt 2010, 14:40

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von wobo »

Also wie gesagt, ich hatte bisher noch keinen einzigen Fehler, bei dem ich sagen konnte, da ist definitiv TP schuld.

Auch der Stack-Fehler war damals wahrscheinlich mein Fehler, da ich in BASM ein paar PUSH/POP-Befehle hatte und im ersten Moment dachte bei 16 kb Stack muß ich mir keine Sorgen wegen einzelner PUSH und POPs machen. Das stimmt natürlich dann nicht, wenn man anderweitig z.B. viele große lokale Variablen anlegt und mit Objekten arbeitet.

Wenn man dann anderweitig an die 16kb-Grenze des Stacks kommt, kann ein PUSH ja schon zuviel sein. Und das Stak-Checking hilft dann natürlich auch nicht, weil die Ursache für den Stack-Überlauf von meinem Assembler-Befehl kommt. Hierfür gelten die xy-Checkings nicht.
Brueggi hat geschrieben: Ansonsten bin ich immer noch ratlos - da eben jedes mal ein anderer Programmteil nicht funktioniert. Wozu ich dann Range-/Stack- und Gedönse-Checking hab, wenn doch nichts geprüft wird... Also bisher kann ich nur sagen, in meinen paar Tausend Zeilen BDOS-Source (Assembler) habe ich Fehler definitiv IMMER schneller gefunden, als in TP. Und das heißt was :-)
Wie gesagt, bei BASM helfen die Range-/Stack- usw. Checkings nichts, da diese nur für Pascal-Befehle gelten.

Aber ich gebe Dir ohne weiteres Recht, dass Fehler unter TP, die nicht sofortige Auswirkungen haben oder von den Range-Checkings erfasst werden, ziemlich schwierig zu finden sind. Ich habe da leider auch kein Patentrezept: Meistens suche ich einen Fehler stundenlang (manchmal sogar Tage), was sehr zermürbend ist.
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Mir wird wohl auch nichts anderes übrig bleiben, als entweder die nächsten Tage mit der Suche zu verbringen, oder nochmal von vorn anzufangen (aber dann wohl gleich in ASM). Einen Versuch hab ich aber noch - ich setze profilaktisch mal alle Parameter in Proceduren auf VAR.

Stack dachte ich ja auch erst - nur kommen im ganzen Source nur 3-4 kleine ASM-Teile vor - und die haben alle brav PUSH und POP :-) Ich hab trotzdem mal mit $M den Stack auf 30000 erhöht. Keine Änderung im Verhalten.
DOSferatu
DOS-Übermensch
Beiträge: 1220
Registriert: Di 25. Sep 2007, 12:05
Kontaktdaten:

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von DOSferatu »

Hinweis: Stack-Überläufe kommen natürlich auch bei rekursiver Programmierung vor (und können natürlich vom Compiler auch nicht abgefangen werden).
Stackbedingte Fehler hatte ich auch schon manchmal.

BTW: Ich habe schon einiges an Debug-Zeug programmiert. Vor allem Programme, die in einen Source Dinge einfügen (also einen neuen Source erstellen).
Das funktioniert dann z.B. so, daß das Programm während der Laufzeit in ein File mitloggt, was das Programm macht (z.B. welche Procedures/Functions aufgerufen werden, MIT den übergebenen Parametern) oder Prüfen von Variablen (oder Funktionswerte), wo dann immer ausgegeben wird, wenn diese sich ändern, mit der entsprechenden Zeilennummer (bezogen auf den ursprünglichen Source).
D.h. man compiliert dann den neuen Source, läßt ihn laufen...
Es ist zwar nicht alles total perfekt - dafür ist es eben schließlich nur ein Debugger - aber bei Dingen, wo nichts anders mehr hilft, habe ich damit schon öfters die entscheidenden Fehler gefunden.
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Auch rekursive Aufrufe kann ich ausschließen. Die tiefste Verschachtelungsebene ist:

Hauptprogramm -> DisplayLinks -> PutIcon (und wenn ein Icon aus einer Anwendung geladen werden soll kommt noch ->GetAPLIcon dazu). Die Proceduren rufen sich dann aber nicht gegenseitig "rückwärts" auf.

Was ich probiert habe ist auch GetMem/FreeMem nicht mehr dort einzusetzen, wo es gebraucht wird, sondern einmalig am Programm-Anfang. Vorläufiges Fazit: Code funktioniert - sobald man aber ein Hintergrundbild lädt, stürzt der Rechner sofort ab. Daher ist langsam mein Verdacht, dass Pointer irgendwie nicht korrekt übergeben werden, z. B.

GetMem(puffer,40000) { Speicher für BMP, einmalig am Programm-Anfang angefordert }
.
.
.
DisplayBMP(bildname,puffer,result) { Unit BMP -> Freeze }

Irgendwie glaube ich, dass die Unit BMP garnicht den Puffer-Pointer bekommt, sondern "irgendwas". Und dieses "irgendwas" sind RAM-Adressen, die sich eben ändern (z. B. von Programmen, die zwischenzeitlich geladen wurden) und daher der Code immer wo anders "aussteigt". Ist wie gesagt mein Verdacht.

Ihr habt natürlich recht - TP kann (und darf z. T. auch) garnicht alles wissen und abfangen. Aber mich ärgert halt, das so dinge wie oben beschrieben (mit dem VAR xxx-Beispiel) nicht angekreidet werden. Wenn man 2000 Zeilen Code hat, findet man so einen Fehler von alleine garnicht.

Auch komisch war mal wieder, dass beim Compilieren aus der IDE heraus alles ok war, während TPC an der Kommandozeile doch noch 2 Fehler gefunden hat (Typen-Fehler bei der Prozedur-Übergabe und einen Schreibfehler). Nun kann ich nur noch probieren, den BMP-Code abzuspecken (dann gehen halt wieder nur 640*480 große BMPs) und direkt in das Hauptprogramm einzubauen. Denn irgendwann verliere ich auch die Lust, mich damit zu beschäftigen. :-( Aber sowas ist halt eventuell der Preis des Real-Modes...

Wie auch immer - wenn es erstmal so stabil bleibt, und der abgespeckte Bild-Code läuft, dann bekommst Du, Wobo, mal eine Test-Version - und ich hoffe, dass der Code dann wenigstens am 386 so läuft, wie am 486.... :-)
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Nur um auszuschließen, dass ich noch einen Denkfehler habe - wenn ich aus einem Dateipuffer (beinhaltet den ersten Sektor einer Datei) in eine Var kopieren will, kann ich dies doch so machen:


PUSH DS
PUSH ES

DI wird mit Ofs(var) geladen,
ES wird mit Seg(var) geladen,
DS und SI mit Dateipuffer laden, CX mit SizeOF(var), dann noch

CLD
REP MOVSB

und am ende noch
POP ES
POP DS

Nicht das ich hier schon einen Denkfehler habe?

Es dürfte doch dann keine Rolle mehr spielen, ob VAR ein Record ist, ein String oder sonstwas? (natürlich weiss ich, dass Byte 0 bei Strings die Länge ist) - In meinem Fall ist VAR ein Record mit verschiedenen Einträgen, wie z. B. X (Word), Y (word), diversen Strings usw.
wobo
DOS-Guru
Beiträge: 614
Registriert: So 17. Okt 2010, 14:40

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von wobo »

Brueggi hat geschrieben:Nur um auszuschließen, dass ich noch einen Denkfehler habe - wenn ich aus einem Dateipuffer (beinhaltet den ersten Sektor einer Datei) in eine Var kopieren will, kann ich dies doch so machen:


PUSH DS
PUSH ES

DI wird mit Ofs(var) geladen,
ES wird mit Seg(var) geladen,
DS und SI mit Dateipuffer laden, CX mit SizeOF(var), dann noch

CLD
REP MOVSB

und am ende noch
POP ES
POP DS

Nicht das ich hier schon einen Denkfehler habe?

Es dürfte doch dann keine Rolle mehr spielen, ob VAR ein Record ist, ein String oder sonstwas? (natürlich weiss ich, dass Byte 0 bei Strings die Länge ist) - In meinem Fall ist VAR ein Record mit verschiedenen Einträgen, wie z. B. X (Word), Y (word), diversen Strings usw.
Ja richtig (solange var im Datensegment liegt. Liegt Var im Heap, dann natürlich Seg(var^), Ofs(var^),SizeOf(var^)...)

Ich denke, ich habe heute auch einen Fehler in der nFileDialog - Procedure aus der gos286.tpu gefunden. Der zurückgelieferte Dateiname ist nur korrekt, wenn der Dateinname nebst Punkt und Extension exakt 12 byte groß ist. Ist er kleiner (z.B. BOXES.APL), so wird zwar ein String der Länge 12 zurückgeliefert. Die nachfolgenden Variablen sind aber "zerschossen" (habe ich das Gefühl). Ich schicke Dir mal einen Testsource zur Verdeutlichung.
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Da bin ich ja erstmal beruhigt, dass ich mit dem Kopier-Code richtig liege.

Das mit NFileDialog - betrifft das nur NFileDialog? Wenn ja, wundert es mich, denn das ist das gleiche wie Filedialog - einziger Unterschied ist ein bestimmtes Byte in der Struktur, das GOS anweist, das LW-/Dir-Wechseln zu verbieten. Ist mir aber auch noch garnicht aufgefallen - natürlich schaue ich mir den Code umgehend nach Erhalt an.
wobo
DOS-Guru
Beiträge: 614
Registriert: So 17. Okt 2010, 14:40

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von wobo »

Brueggi hat geschrieben:Da bin ich ja erstmal beruhigt, dass ich mit dem Kopier-Code richtig liege.

Das mit NFileDialog - betrifft das nur NFileDialog? Wenn ja, wundert es mich, denn das ist das gleiche wie Filedialog - einziger Unterschied ist ein bestimmtes Byte in der Struktur, das GOS anweist, das LW-/Dir-Wechseln zu verbieten. Ist mir aber auch noch garnicht aufgefallen - natürlich schaue ich mir den Code umgehend nach Erhalt an.
Email ist gerade raus. Ob das Problem auch bei FileDialog auftritt, habe ich nicht getestet.
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Mail ist angekommen. Ich übertrag mir das nachher gemütlich bei einem Bierchen mal zur DOSe. Mein erster Verdacht: Da GOS das Textfeld der File-Dialogbox mit 0-Bytes füllt, vermute ich, dass der Dateiname dann ein (oder mehrere) CHR(0) angehängt bekommt. Und 0-Bytes zeigen BonnyDOS und GOS immer das Ende eines Strings an. Deswegen dürfte der Rest der Meldung in der Alert Box fehlen... Ich checke das mal im GOS-Code (danke auch für die neue LEDIT-Version!).

Wahnsinn, was Du alles so testest - darauf wäre ich nie gekommen :-) Was Du schon alles für Bugs gefunden hast! Vielen Dank dafür! So macht das auch Spaß, wenn man Rückmeldungen bekommt.
Brueggi

Re: Probleme mit TP 7 - Seltsames Verhalten der Programme

Beitrag von Brueggi »

Soo... Zwischenbericht. Ich habe den Sonntag von früh bis abends jede einzelne Zeile des Codes durchgeschaut - nirgends trifft man auf sachen wie

Procedure XY(xy: xxx);
begin;
xy:=xxxx;
end;

oder ähnliche Fehler.

Alles korrekt. Dort wo Var sein soll, da steht es auch. Alle ASM-Blöcke sind korrekt, BP, SS und SP bleiben unberührt, nur DS und ES werden geändert - aber jedesmal gesichert und wieder restauriert.

Was ich herausgefunden habe: Offenbar kompiliert TP mir meine VARs (die globalen) direkt in die Procedures rein, bzw. andere Procedures "über" procedures. Wie ich darauf komme? Nun:

1. Ich ändere die Reihenfolge der Procedures nach dem VAR oben im Code -> die erste Procedure nach VAR streikt sofort, alle anderen scheinbar zufällig (sicherlich durch den Müll dann, der entstanden ist)
2. Ändere ich VARs (Array-Anzahl usw.) verhält sich besagter Punkt 1 wieder anders
3. Ich füge Proceduren in den Code ein -> Nachfolgende Procedures streiken

Somit bin ich nun da angekommen, dass ich das Projekt wohl komplett einstelle, oder alle geplanten Features soweit zusammen streiche, das keine Fehler auftauchen. Woran das nun letztendlich liegt, dass TP so einen "Müll" kompiliert, weiss ich nicht.

Ich verwende nur 3 (jetzt nur noch 2) Units - die funktionieren bei bisher ein dutzend Programmen PRoblemlos und brauchen selbst auch (Fast) keine VARs (auch keinen Init-Part). Selbst die (jetzt gestrichene) BMP-Unit läuft beim Publisher (der wesentlich größer und komplexer ist vom Code her).

Ich bin diesbezüglich ehrlich etwas "angepxxxxst" - denn von 20h Programmierung dann 12h damit zu vebringen, sich mit sowas rumzuschlagen, spricht für mich nicht gerade von Qualität. Natürlich kann ein Kompiler nicht alles abfangen oder prüfen (und wenn, wäre der Code extrem lahm) - aber sowas ist doch seeeehhhrr krass. Ich werde entweder mal FreePascal testen oder mit C anfangen - besser gleich bei ASM bleiben, da hatte ich sowas zwar auch mal, aber nur deswegen, weil ein REP MOVSx ausversehen ins falsche Segment gewandert ist ;-) Aber immerhin findet man sowas auf Anhieb.

Auffällig war auch (mal) wieder, dass in der IDE Compile->Make (oder Build - geht beides) keinen Fehler anzeigt ("Successfull") und TPC am Prompt mir auf einmal Type Mismatches anzeigt, sowie diverse (richtig angeprangerte) Schreibfehler... Das alleine ist mir schon suspekt, da ich dachte, TPC und die IDE machen das gleiche bzw. rufen das gleiche Programm auf....
Antworten