ENGLISH VERSION |
|
Links | | | Forum | | | Kommentare | | | News melden |
Chat | | | Umfragen | | | Newsticker | | | Archiv |
amiga-news.de Forum > Programmierung > Umsetzung StormC 4 -> gcc | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
-1- | [ - Beitrag schreiben - ] |
24.04.2006, 20:40 Uhr Uwe Posts: 74 Nutzer |
Ich versuche gerade ein größeres Projekt (Portierung von ScummVM) von StormGCC auf gcc 2.95.3 umzusetzen. Das scheint nicht ganz einfach zu sein. :-( Scheinbar gibt es Unterschiede in der Implementierung der ANSI-C-Bibliotheken. Ein Beispiel: Im Programm kommen Stellen vor, bei dem versucht wird 0 Byte Speicher anzufordern (ist nicht meine Idee). StormC liefert bei malloc(0) einen gültigen Zeiger. gcc/ixemul stürzt bei einem malloc(0) ab, da laut ixemul-Sourcen direkt auf AllocMem(0, ...) abgebildet wird. Gibt es noch andere Inkompatibilitäten, besonders wie oben bei Grenzsituationen? Gibt es Hinweise und Tipps, die eine "Umsetzung" erleichtern? Uwe PS: libnix funktioniert auch nicht (fehlende Funktionen, weitere Inkompatibilitäten) [ - Antworten - Zitieren - Direktlink - ] |
24.04.2006, 22:50 Uhr Holger Posts: 8116 Nutzer |
Zitat:Kann so eigentlich nicht sein. Die bei malloc() belegte Größe wird für free() gepeichert. Also entweder wird auf AllocVec() gemappt, oder bei AllocMem() mind. 4 bytes für die Größeninformation zur Anforderung hinzugefügt. Im letzteren Fall dürfte es demzufolge kein Absturz geben. Und im Falle von AllocVec hätte ich vermutet, daß es genauso funktioniert, weil ebenfalls mind. 4 bytes benötigt werden. Zitat:Neuere gcc-Version verwenden. Damit nicht bei einem späteren Wechsel neue Inkompatiblitäten auftreten. Außerdem ist der code, den Du portieren willst, bestimmt außerhalb der Amiga-Welt mit einem neueren gcc getestet worden. Die gleiche Generation zu verwenden, kann viel Ärger ersparen. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
24.04.2006, 23:08 Uhr Holger Posts: 8116 Nutzer |
Hab mal rasch den Test gemacht (AOS3.9) AllocVec(0, ..) und AllocMem(0, ..) liefern NULL zurück (kein Absturz), AllocMem(4, ..) funktioniert erwartungsgemäß und malloc(0) übersetzt mit gcc3.4.0 liefert einen Pointer, wird also vermutlich wirklich auf AllocMem(x+4, ..) abgebildet. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
25.04.2006, 09:29 Uhr gni Posts: 1106 Nutzer |
Zitat:Gibt es wirklich einen Crash? Bei Allokationen <MINSIZE wird MINSIZE allokiert. Und nur Größen über einem bestimmten Limit werden direkt per AllocMem() bedient. Zitat:Was fehlt? Welche weiteren Inkompatibilitäten? Zumindest liefert malloc(0) einen gültigen Zeiger, wenn ich die Quellen des libnix-malloc richtig lese. ixemul müßte laut Quellen auch einen gültigen Zeiger liefern. Davon abgesehen, Du willst garantiert für scummvm kein ixemul. [ - Antworten - Zitieren - Direktlink - ] |
25.04.2006, 19:39 Uhr Uwe Posts: 74 Nutzer |
Ich habe noch mal genau nachgesehen. Es war nicht malloc(0), sondern calloc(x,0). Und nur bei libnix stürzt es ab. Ich habe mir mal die libnix-Sourcen abgesehen und etwas experimentiert. code:void *calloc(size_t nmemb,size_t size) { size_t l; size_t *a; void *b; l=(nmemb*size+(sizeof(size_t)-1))&~(sizeof(size_t)-1); a=(size_t *)(b=malloc(l)); if(b!=NULL) { do *a++=0; while((l-=sizeof(size_t))!=0); } return b; } Ist einer der Argumente 0 ist auch l = 0. malloc(0) liefert einen gültigen Zeiger. Danach wird vom Zeiger aus die nächsten 4 GB Speicher gelöscht. l ist 0 und wird um 4 verringert (=4G-4) und auf 0 geprüft ... Was bei libnix fehlte probiere ich nochmal aus. [ - Antworten - Zitieren - Direktlink - ] |
25.04.2006, 21:33 Uhr Holger Posts: 8116 Nutzer |
Zitat:Wow, ja das ist C-Code der alte Schule. Immer nach dem Motto "je krypischer es aussieht, desto höher muß wohl die Performance sein". Tja, irgendwann fällt so ein Mist jemanden auf die Füße, und wie so oft, jemanden, der nix dafür kann. Gut, daß es OSS war und Du die Ursache gefunden hast. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
26.04.2006, 08:58 Uhr gni Posts: 1106 Nutzer |
Zitat:Welche Stelle verstehst Du nicht? Zitat:Woher nimmst Du diese Weisheit? Zitat:Ein Glück wir haben "Experten" wie Dich :-/ [ - Antworten - Zitieren - Direktlink - ] |
26.04.2006, 10:46 Uhr Holger Posts: 8116 Nutzer |
Zitat:Ich versteh den code schon. Aber wie lange ich dafür gebraucht habe, steht in keinem Verhältnis zu dem, was er macht. Zitat:Hallo? Willst Du jetzt nur aus Prinzip diskutieren?Zitat:Woher nimmst Du diese Weisheit? Schau Dir doch bitte diesen Code mal an: do *a++=0; while((l-=sizeof(size_t))!=0); Statt einer for-Schleife benutzt man eine do-while Schleife, warum? Weil man eine Vortest einsparen wollte (was dann bei Uwe für den Absturz gesorgt hat)? Statt einer for-Schleife mit einfachen Zähler benutzt man einen Dekrement -= und zwar innerhalb eines logisches Tests, warum? Weil es Performance bringt, im Quellcode vielleicht eine Zeile zu sparen? Oder weil halt im Handbuch für esoterische Optimierungen steht "do..while ist schneller als for", "Dekrement in logischen Ausdruck einsetzen ist schneller, als in in eigene Anweisung zu schreiben", "Test auf 0 ist schneller als kleiner als" oder einfach nur "wenn's jemand auf Anhieb lesen kann, ist's zu langsam"? Zitat:Was hat das mit Experten zu tun? Jeder Anfänger hätte geschrieben: for(i=0; i<l; i++) a[i]=0; und dieser Code hätte funktioniert und das wär auch auf Anhieb erkennbar gewesen. Vielleicht mit einem Promille weniger Performance, aber das was dieser Code an mehr Zeit benötigt hätte wäre immer noch ein Bruchteil dessen, was Uwe jetzt an Zeit investieren mußt, um den Fehler zu finden. Fall jetzt immer noch jemand nicht versteht, warum es sinnvoll ist, lesbaren Code zu schreiben, werde ich nicht weiter mit ihm diskutieren. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
26.04.2006, 13:25 Uhr gni Posts: 1106 Nutzer |
Zitat:Offensichtlich hat vorher niemand 0-Bytes mit calloc() angefordert. IMHO ist das der wirkliche Bug. [ - Antworten - Zitieren - Direktlink - ] |
26.04.2006, 16:51 Uhr Holger Posts: 8116 Nutzer |
Zitat:Das ist wohl soweit vollkommen richtig. Es ist trotzdem so, daß es für viele Aufgaben eine kanonische Art, es zu implementieren, gibt, wie man sie auch in jedem C-Lehrbuch finden kann. Wie zum Beispiel die Trivialität, zum Iterieren über <was auch immer> eine for-Schleife zu verwenden. Und mit dieser wäre der Fehler gar nicht erst passiert. Ich weiß, daß meine Vermutung, der Autor dieses Codes wäre von der üblichen Praxis aus Performance-Erwägungen abgewichen, reine Spekulation ist. Vieles spricht aber Angesicht der anderen Eigenheiten dafür, vor allem, da die zweitnaheliegenste Begründung, wenig C-Erfahrung, deutlich unwahrscheinlicher ist. Ich habe letztendlich nur meinem Entsetzen beim Anblick des Stück Codes Audruck verliehen. Wenn andere weniger Unbehagen beim Betrachten dieses Fragments empfinden, was solls. Ich persönlich bin froh, daß die AOS-Funktionen beim Anfordern von 0 bytes nicht mit einem Absturz reagieren. Ich denke, damit ist alles zu diesem Thema gesagt. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
26.04.2006, 21:36 Uhr Dietmar Posts: 166 Nutzer |
@Holger: > for(i=0; i<l; i++) a[i]=0; Warum nicht: code:In der Annahme, dass Vergleiche gegen 0 schneller sind, als in jedem Durchlauf i mit l zu vergleichen.i = l; while (i) a[--i] = 0; [ - Antworten - Zitieren - Direktlink - ] |
27.04.2006, 09:10 Uhr gni Posts: 1106 Nutzer |
Zitat: Oder so? code:for(;l!=0;l-=sizeof(size_t)) *a++ = 0; [ - Antworten - Zitieren - Direktlink - ] |
27.04.2006, 12:48 Uhr Holger Posts: 8116 Nutzer |
Zitat: Weil es relativ sinnlos ist, solche Annahmen zu machen. Ansonsten sind nunmal for-Schleifen das Konstrukt der Wahl, wenn man iterieren will. Das erhöht nicht nur die Lesbarkeit, sondern bietet auch dem Compiler besser Möglichkeiten, die Intention zu verstehen und zu optimieren. Wenn man überhaupt davon ausgeht, daß der Compiler guten Code erzeugen kann. Andernfalls ist es egal, ob man mit 0 oder einem anderen Werte vergleicht, wenn der vom Compiler generierte Overhead zehnmal größer ist als dieser Unterschied. Von daher ist gni's Variante besser: for(;l!=0;l-=sizeof(size_t)) *a++ = 0; weil sie Schleifenbedingung und zugehörige Dekrementanweisung da zusammenfaßt, wo sie hingehören. Aber bei den meisten Prozessoren ist die Verwendung zweier Variablen, die beide in jedem Durchlauf verändert werden, aufwändiger als der Unterschied zwischen einem Test auf 0 und einem Vergleich. Somit ist folgendes besser: for(b=a+l; a!=b; a++) *a=0; Das reduziert die absolute Anzahl an Operationen, was i.A. mehr bringt als der Ersetzen eines Vergleichs durch einen Test auf 0. Allerdings ist der Effekt auf Prozessoren mit parallel arbeitenden Units sehr gering, nur der Schreibzugriff und der Vergleich können parallelisiert werden, aber beide Operationen müssen auf das Inkrement warten. Dieses Problem kann mit Loop-Unrolling mit parallelisierbaren Anweisungen gelöst werden, aber es wäre sinnlos, das von Hand zu machen, weil die richtige Anzahl von "ausgerollten" Iterationen vom Zielprozessor abhängt und falsche Annahmen kontraproduktiv sind. Beim 68k sind das eh maximal zwei integer Einheiten und die Load/Store Unit, die parallel arbeiten können. (Der Sprungbefehl wird vom Prozessor korrekt wegoptimiert...) mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
27.04.2006, 16:36 Uhr gni Posts: 1106 Nutzer |
Zitat:Am besten ist was ganz anderes: Man nehme bzero/memset, dann hätte es den Bug auch nicht gegeben. Aber genau die Funktionen sollten da vermieden werden. [ - Antworten - Zitieren - Direktlink - ] |
27.04.2006, 16:47 Uhr Holger Posts: 8116 Nutzer |
Zitat:Müssen die nicht auch innerhalb von libnix implementiert werden? Vielleicht sollte man, wenn man schon dabei ist, da auch mal einen kritischen Blick drauf werfen... Aber evtl. delegieren die auch nur an eine AOS-Funktion. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
27.04.2006, 18:04 Uhr gni Posts: 1106 Nutzer |
Zitat:bzero nicht, aber beide sind vorhanden. Zitat:Mach mal... Zitat:Welche sollte das sein? [ - Antworten - Zitieren - Direktlink - ] |
27.04.2006, 21:42 Uhr Uwe Posts: 74 Nutzer |
Bevor ihr euch weiter wegen Kleinigkeiten streitet, hier ein noch gravierender Fehler bei libnix 2.1 (ältere Versionen habe ich nicht probiert). code:#include <stdio.h> int main(int argc, char **argv) { FILE *file1, *file2; int a,b; char buffer1[10]; char buffer2[10]; file1 = fopen("datei1", "rb"); file2 = fopen("datei2", "rb"); if (file1 && file2) { a = fread(buffer1, 1, 10, file1); b = fread(buffer2, 1, 10, file2); fclose(file1); fclose(file2); } return 0; } Ausgaben (im Code weggelassen): a = 10; buffer1 = (ersten zehn Bytes von file2, in Worten Zwei) b = 0; Das Öffnen der zweiten Datei scheint irgendwie die File-Strukturen durcheinanderzubringen. file1 scheint auf die zweite Datei zu zeigen. file2 scheint ungültig zu sein (aber != NULL). Das gleiche mit ixemul funktioniert. Mal nebenbei: Ich habe mal versucht die libnix-Bibliotheken neuzukompilieren: Das makefile schlägt immer fehl: make[1]: *** No rule to make target 'nrcrt0.S', needed by 'nrcrt0.o'. Stop. Version von make: 3.80 Version von gcc: 2.95.3 Nachtrag: Ich habe mal das gleiche mit open/close/read probiert und es funktioniert. Da fopen/fclose/fread darauf basieren muss der Fehler dazwischen liegen. [ Dieser Beitrag wurde von Uwe am 27.04.2006 um 22:07 Uhr geändert. ] [ - Antworten - Zitieren - Direktlink - ] |
27.04.2006, 22:52 Uhr Holger Posts: 8116 Nutzer |
Zitat:Tun wir nicht, wir diskutieren nur Zitat:Dir ist schon klar, daß das nicht ganz sauber ist?C code:file1 = fopen("datei1", "rb"); file2 = fopen("datei2", "rb"); if (file1 && file2) { fclose(file1); fclose(file2); } Was den Fehler angeht, muß ich mir erstmal genauer ansehen... mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
28.04.2006, 00:08 Uhr Holger Posts: 8116 Nutzer |
@Uwe: Also bei mir macht Dein Code das richtige. Habe gcc3.4.0 verwendet, kann also meinen Ratschlag nur noch mal bekräftigen: probier's mit 'ner neueren gcc-Version. Bzw. Umgebung, habe ja libnix und gcc aus ein und derselben Umgebung, vielleicht kann man die auch einzeln installieren, aber ich glaube nicht, daß sich der Aufwand manueller einzel-Installationen lohnt. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
28.04.2006, 09:04 Uhr Stefan Posts: 936 Nutzer |
@Uwe: Hallo Uwe, Probiere doch mal den "GCC 3.4". Vielleicht klappt es damit und mache hin , damit es bald eine neue Scumm-Version gibt. Der GCC 3 lässt sich parallel zur Version 2.95 betreiben. Ich habe das auch so installiert und es funktioniert. Auszug aus der 3.4.0-Notes | - installation: | To be able to use GCC 2.x and GCC 3.x at the same time, its | recommended to install the frontend programs in bin/ with an | added "3" eg. as gcc3. | Executing an older GCC version from the V3 frontend is possible | with -V<version> if the frontend for <version> is installed as | gcc-<version>. Gruß Stefan [ - Antworten - Zitieren - Direktlink - ] |
28.04.2006, 20:31 Uhr Uwe Posts: 74 Nutzer |
@HolgerZitat: Das sollte nur ein kurzes Beispiel sein. @Holger, Stefan Ich habe mal gcc 3.3 verwendet. Das gleiche. Es liegt an libnix. Bei Version 1.2 geht es, ab 2.0 nicht mehr. Ich habe 2.1 installiert gehabt. Version 1.2 ist immer bei den gcc-Paketen dabei. >2.0 gibt's auf der libnix-Homepage (bei Sourceforge.net). Der Fehler muss also in der Version 2.0 hereingekommen sein. MfG Uwe [ - Antworten - Zitieren - Direktlink - ] |
29.04.2006, 10:38 Uhr gni Posts: 1106 Nutzer |
Zitat:Die basiert auf einer Beta-Version, die einige schwerwiegende Fehler hatte. Zitat:Was neueres wurde auch nie offiziell rausgegeben. Zitat:Das ist _nicht_ die Homepage von libnix. Es gibt keine. [ - Antworten - Zitieren - Direktlink - ] |
-1- | [ - Beitrag schreiben - ] |
amiga-news.de Forum > Programmierung > Umsetzung StormC 4 -> gcc | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
Impressum |
Datenschutzerklärung |
Netiquette |
Werbung |
Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten. |