amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > gcc und Messages aargh [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

27.03.2004, 16:14 Uhr

Inferno
Posts: 157
Nutzer
Hi,

habe hier ein Problem mit gcc. Ich habe die GoldED - Installation von gcc drauf. Wenn ich folgendes kleines Programm compiliere, stürzt mir der Rechner gnadenlos ab:

------
#include <proto/exec.h>
#include <proto/dos.h>
#include <dos/dostags.h>
#include <stdio.h>
#include <clib/alib_protos.h>

MsgPort *port = NULL;

void __saveds threadProc() {
Delay(20);
Message *msg = new Message;
PutMsg(port, msg);
Delay(20); // Allow message to be received!!
delete msg;
return;
}

int main() {
if((port = CreatePort(NULL, 0))) {
struct Process *proc = CreateNewProcTags(NP_Entry, (long unsigned int)threadProc, NP_StackSize, 16384, NP_Name, (long unsigned int)"Thread1", TAG_END);
if(proc) {
WaitPort(port);
printf("Message arrived\n");
}
DeletePort(port);
}
}

-----

mit c++ test.cpp compiliert und a.out ausgeführt.

Dann sehe ich gerade noch "Message arrived" im Shell-Fenster und dann den Absturz.

Was mache ich hier falsch?

Danke im voraus,

Inf!

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 16:43 Uhr

Mad_Dog
Posts: 1944
Nutzer
Wie wär's mit return 0? ;)
--

http://www.norman-interactive.com

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 16:49 Uhr

Inferno
Posts: 157
Nutzer
Kleiner Nachtrag:

Wenn ich in der "threadProc" die Zeile "delete msg" auskommentiere, funktionierts!!!!!

*grübel*

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 17:18 Uhr

thomas
Posts: 7716
Nutzer

Du solltest dir ein vernünftiges Protokoll ausdenken, mit dem du sicherstellst, daß

1. Speicher nicht freigegeben wird, wenn er noch benutzt wird
2. das Programm nicht verlassen wird, bevor alle Subtasks beendet sind.

D.h. dein Thread sollte einen Reply-Port öffnen und warten, bis die Haupttask die Message beantwortet (GetMsg+ReplyMsg). Weiter sollte dein Hauptprogramm am Ende prüfen, ob die Subtask beendet wurde und ggf. warten, bis es soweit ist.

Hier ist ein funktionierendes Beispiel: http://home.t-online.de/home/thomas-rapp/download/multi.c


Gruß Thomas

--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 18:25 Uhr

Inferno
Posts: 157
Nutzer
Hallo Thomas,

danke für die Info.
Dein Programm funktioniert so weit. Aber sobald ich aus der Message einen Pointer mache und diesen vor jedem senden "new"e und nach dem Delay wieder "delete", stürzt er beim ersten "delete" ab....

Komisch...

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 18:27 Uhr

Inferno
Posts: 157
Nutzer
Noch was anderes:

er findet die "proto/alib.h" nicht, ich muss stattdessen immer "clib/alib_protos.h" verwenden. Auch auf der OS 3.5 developer CD ist die alib.h nicht drauf. Wo kriege ich die her??

Gruß,

Inf

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 18:34 Uhr

thomas
Posts: 7716
Nutzer

Zitat:
Dein Programm funktioniert so weit. Aber sobald ich aus der Message einen Pointer mache und diesen vor jedem senden "new"e und nach dem Delay wieder "delete", stürzt er beim ersten "delete" ab....

Vermutlich ist C++ nicht reentrant. Versuch's mal mit AllocVec() und FreeVec(). Du kannst aus dem gleichen Grund in Subtasks auch nicht printf() verwenden, aber dos.library/Printf() funktioniert.

Zitat:
er findet die "proto/alib.h" nicht, ich muss stattdessen immer "clib/alib_protos.h" verwenden. Auch auf der OS 3.5 developer CD ist die alib.h nicht drauf. Wo kriege ich die her??

proto/xy.h ist nur eine Kombination aus xy_protos.h und xy_pragmas.h. Da es für die alib keine Pragmas gibt (ist ja keine externe Library, sondern eine Linker-lib), gibt es auch kein proto/alib.h. Fazit: für die alib mußt du immer nur clib/alib_protos.h einbinden (und sicherstellen, daß der Linker die amiga.lib einbindet).

Gruß Thomas
--
Email: thomas-rapp@web.de
Home: home.t-online.de/home/thomas-rapp/

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 18:41 Uhr

Inferno
Posts: 157
Nutzer
Hallo Thomas,

genau das wars....

Jetzt habe ich nur ein Problem:
Ich muß alle "news" & "deletes" in einem 200000 Zeilen StormC Quellcode in AllocVec/FreeVec ändern.

Klingt schwer nach "Operatoren überladen"!

Vielen Dank für den Tip! Kriegst auch Credits im Fertigen Produkt

Inf.

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 22:08 Uhr

Inferno
Posts: 157
Nutzer
Hi,

Wenn das wirklich so ist, daß new und delete nicht reentrant sind, was mache ich denn dann bei Objekten? Sprich, wie rufe ich Konstruktor und Destruktor auf, wenn ich alles über AllocVec / FreeVec realisiere?

Ich habe eher das gefühl, daß ich falsche / alte Libraries habe.

Die amiga.lib hier ist Version 45.3 und 226852 bytes groß.

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 22:20 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Inferno:
Wenn das wirklich so ist, daß new und delete nicht reentrant sind, was mache ich denn dann bei Objekten? Sprich, wie rufe ich Konstruktor und Destruktor auf, wenn ich alles über AllocVec / FreeVec realisiere?

Ich glaube nicht, daß das Problem dort liegt.
Hast Du, nach der Änderung des Beispielprogramms von statisch zu dynamisch erzeugten Messages auch die Stelle mit der Message-Länge (sizeof(...)) geändert?
Und an welcher Stelle in dem Programm hast Du die new und delete Anweisungen eingefügt?

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

27.03.2004, 22:57 Uhr

Inferno
Posts: 157
Nutzer
Hallo Holger,

Du kannst meinen kurzen Code von oben nehmen. Ersetze das new/delete durch eine statische Message (auf dem Stack) und es funktioniert. Mit new & delete gibts 'nen crash.

Ich habe Thomas' multi.c wie folgz verändert:
1) Bei der Definition statt "struct Message mymsg" eben struct Message *mymsg"

2) Nach dem "DateToStr(&dt);" - Aufruf eine Zeile "mymsg = new Message" eingefügt.

3) alle mymsg. - referenzen in mymsg-> geändert

4) Bei PutMsg anstat &mymsg nur mymsg

5) Nach der Zeile "Delay(50)" Eine Zeile "delete mymsg;" eingefügt

Und schon kommt der crash :(

Gruß,

Inf.

Ups, vergessen: Natürlich habe ich auch die Länge in sizeof(struct Message) geändert

[ Dieser Beitrag wurde von Inferno am 27.03.2004 editiert. ]

[ - Antworten - Zitieren - Direktlink - ]

28.03.2004, 00:49 Uhr

whose
Posts: 2156
Nutzer
Ich weiß, ich werde bestimmt wieder verbal gesteinigt, weil ich das sage, aber:

Mit StormC3 compiliert läufts einwandfrei, auch wenn das kleine Prog alles andere als sauber ist.

Ist eine der "Merkwürdigkeiten", die der GCC in seiner 68K-Variante schon ne Ewigkeit mit sich rumschleppt. Der 2.95.2 macht da auch ein absturzfreudiges Programm draus. Der delete-Operator hat wohl ein generelles Problem mit lokalen Variablen.

Im übrigen erfolgt der Absturz erst bei Austritt aus dem Hauptprogramm, also beim cleanup.

Vielleicht sollte man Heinz Wrobel mal zu diesem Problem befragen, er hat bestimmt eine Lösung dafür parat.

Grüße

[ - Antworten - Zitieren - Direktlink - ]

28.03.2004, 19:51 Uhr

Inferno
Posts: 157
Nutzer
Problem gelöst, funzt jetzt auch mit new & delete !!!

Problam war (wie so oft) benutzerfehler :)

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

29.03.2004, 01:02 Uhr

whose
Posts: 2156
Nutzer
Teilst Du uns denn auch noch mit, was genau das Problem war? Ich komme da nämlich jetzt nicht so einfach drauf. Wäre nett! :)

Grüße

[ - Antworten - Zitieren - Direktlink - ]

29.03.2004, 04:12 Uhr

whose
Posts: 2156
Nutzer
Ich weiß zwar nicht, was Inferno verkehrt gemacht hat, aber bei mir läufts jetzt auch, nachdem ich bei seinem kleinen Prog die Logik ein bißchen verändert hab ;)

So, wie das Prog da oben steht, beendet der Vaterprozess, bevor der Kindprozess beendet (der wartet nämlich ein bißchen, während der Vaterp. munter weiterläuft und sich beendet). Das haut dann natürlich nicht mehr hin, weil zu dem Zeitpunkt bereits alle Daten des Programms (inkl. Subprozess und zu delete nde msg) aus dem Speicher verschwunden sind. Also nicht die Merkwürdigkeit vom GCC *stirnklatsch* ;)

Grüße

[ - Antworten - Zitieren - Direktlink - ]

29.03.2004, 10:20 Uhr

Inferno
Posts: 157
Nutzer
Hi whose,

-noixemul hat bei mir geholfen. Hatte es schlicht im Makefile vergessen....

Der Code-Ausschnitt oben war nur ein sehr kleiner aus 'nem riesigen Projekt, aber der Absturz kam auch, wenn man in der main-Prozedur noch auf das Beenden des Sub-Prozesses wartet. Lag eindeutig an der delete-Funktion.... und natürlich am vergessenen noixemul.

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

29.03.2004, 10:41 Uhr

whose
Posts: 2156
Nutzer
Zitat:
Original von Inferno:
Hi whose,

-noixemul hat bei mir geholfen. Hatte es schlicht im Makefile vergessen....

Der Code-Ausschnitt oben war nur ein sehr kleiner aus 'nem riesigen Projekt, aber der Absturz kam auch, wenn man in der main-Prozedur noch auf das Beenden des Sub-Prozesses wartet. Lag eindeutig an der delete-Funktion.... und natürlich am vergessenen noixemul.


Ah, okay, danke. Ich hatte es auch mit dem StormC4-GCC probiert, der arbeitet defaultmäßig ohne ixemul.

Jetzt wäre nur noch interessant zu wissen, in wie weit ixemul den delete-Operator des GCC3.x beeinflußt, daß sowas passieren kann...

Grüße


[ - Antworten - Zitieren - Direktlink - ]

29.03.2004, 14:31 Uhr

Inferno
Posts: 157
Nutzer
In der Tat. Aber vielleicht habe ich auch ne uralt-Version der ixemul.library drauf. Ich schaue heute abend mal nach (bin z.Zt. im Büro).

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

29.03.2004, 18:23 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von whose:
Jetzt wäre nur noch interessant zu wissen, in wie weit ixemul den delete-Operator des GCC3.x beeinflußt, daß sowas passieren kann...

Vermutlich so:
new und delete rufen Funktionen der ixemul.library auf und diese unterstützt möglicherweise parallele Ausführung nur, wenn die Threads auch über die ixemul.library erzeugt wurden.
Mit -noixemul wird eben mit einer anderen Bibliothek verlinkt, die wie der Name schon sagt, nicht die ixemul.lib für die Speicherverwaltung benutzt.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 11:41 Uhr

gni
Posts: 1106
Nutzer
Zitat:
Inferno:
Ich habe Thomas' multi.c wie folgz verändert:
1) Bei der Definition statt "struct Message mymsg" eben struct Message *mymsg"

2) Nach dem "DateToStr(&dt);" - Aufruf eine Zeile "mymsg = new Message" eingefügt.

3) alle mymsg. - referenzen in mymsg-> geändert

4) Bei PutMsg anstat &mymsg nur mymsg

5) Nach der Zeile "Delay(50)" Eine Zeile "delete mymsg;" eingefügt

Und schon kommt der crash :(

Was nicht überraschend ist. Lies nochmal den ersten Kommentar von Thomas im Thread und denk drüber nach.
PS: Nachrichten für IPC _müssen_ in PUBLIC Speicher sein. Das garantiert Dir kein malloc/new (es sei denn, Du kannst deren Verhalten beinflussen oder hast diese Funktionen selber implementiert). Wenn Du wirklich die Message freigeben möchtest, dann mußt Du _zwingend_ ein WaitPort drin haben um auf das ReplyMsg() zu warten. Danach kannst Du die Nachricht freigeben.

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 15:09 Uhr

Inferno
Posts: 157
Nutzer
Zitat:
gni:
Lies nochmal den ersten Kommentar von Thomas im Thread und denk drüber nach.


Okay, GENAU DAS MACHT das multi.c - Programm ja auch. Warten auf den Reply, etc. Der Crash kam aufgrund der ixemul - library....
Letzten Endes funktionieren ALLE Versionen, wenn sie mit -noixemul kompiliert werden!

Was den public-Speicher angeht, sehe ich allerdings einige Probleme kommen. Was mache ich denn, wenn ich in einer Message einen Zeiger auf ein Objekt übergeben will? Das kann ich ja nur korrekt über "new" erzeugen (oder kann mir jemand sagen, wie ich konstruktor- und destruktor-Aufrufe nach 'nem AllocVec ausführe?

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

01.04.2004, 15:14 Uhr

Solar
Posts: 3680
Nutzer
Evtl. hilft Dir "placement new" weiter.

[ - Antworten - Zitieren - Direktlink - ]

02.04.2004, 09:22 Uhr

Inferno
Posts: 157
Nutzer
Danke für den Tip, ist aber ziemlich von hinten durch die Brust ins Auge!!

Gibts da keinen "sauberen" Weg, z.B. durch Parametrisierung des gcc?

(a la gcc -noixemul -publicnew)

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]

02.04.2004, 12:10 Uhr

gni
Posts: 1106
Nutzer
Zitat:
Original von Inferno:
Zitat:
gni:
Lies nochmal den ersten Kommentar von Thomas im Thread und denk drüber nach.

Okay, GENAU DAS MACHT das multi.c - Programm ja auch. Warten auf den Reply, etc.
Vergiss multi.c. Das ist kein gutes Beispiel. DOS-Prozesse entfernt man _nicht_ mit RemTask(). Dann verwendet der Subtask GetMsg ohne Prüfung des Ergebnisses.
Zitat:
Der Crash kam aufgrund der ixemul - library.... Letzten Endes funktionieren ALLE Versionen, wenn sie mit -noixemul kompiliert werden!
Der Crash liegt _nicht_ an ixemul! Der Fehler liegt bei Dir, weil etwas falsch verwendest. Auch wenn es mit -noixemul funktioniert, heisst das nicht, das es richtig ist. Du hast nur "Glück".

[ - Antworten - Zitieren - Direktlink - ]

02.04.2004, 12:46 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Inferno:
Danke für den Tip, ist aber ziemlich von hinten durch die Brust ins Auge!!

Gibts da keinen "sauberen" Weg, z.B. durch Parametrisierung des gcc?

(a la gcc -noixemul -publicnew)

Das kann ja nicht der Sinn der Sache sein. Du hast nunmal zwei Möglichkeiten
a) Du ignorierst die Tatsache, daß es ein public flag für Speicher im AmigaOS gibt, weil es eh nicht benutzt wird
oder
b) Du versuchst ein wie auch immer funktionierendes (ich glaube nicht daran) Speichermodell eines zukünftigen OS zu unterstützen, in dem Du das public flag richtig benutzt, also nur dann setzt, wenn das entsprechende Objekt tatsächlich von verschiedenen tasks zugänglich sein soll.
Ein generelles setzen des flags mit einer Art "-publicnew" Option wäre jedenfalls genauso falsch, wie es nie zu setzen.

Vermutlich gibt es genausoviel Programme, die immer public-mem anfordern, wie Programme, die das flag nie setzen. Und zusammen sind das 99% aller existierenden. Deshalb ist auch nicht zu erwarten, daß zukünftige Betriebssysteme mit Abwärtskompatibilität das flag jemals benutzen werden.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

02.04.2004, 13:33 Uhr

Solar
Posts: 3680
Nutzer
Zitat:
Original von Inferno:
Gibts da keinen "sauberen" Weg, z.B. durch Parametrisierung des gcc?


Gibt es. Die operatoren new() und delete() so überladen, das sie AllocMem() und FreeMem() so aufrufen, wie Du das brauchst...

[ - Antworten - Zitieren - Direktlink - ]

02.04.2004, 23:18 Uhr

Inferno
Posts: 157
Nutzer
Ein alternativer Vorschlag wäre mittels #pragmas jeweils umzustellen, wäre wohl am "saubersten". Aber überladen ist auch in Ordnung, solange man es nicht auf mehreren Platformen compilieren will, dann braucht's dafür auch noch nen Haufen #ifdefs :)

Naja, der Quähl-Code wimmelt jetzt schon vor lauter defines für Mac, Amiga, AROS, etc....

Gruß,

Inf.

[ - Antworten - Zitieren - Direktlink - ]


-1- [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > gcc und Messages aargh [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.