Probleme bei calloc - bei großen Feldern



  • ...tatsächlich NULL zurück.

    Ich habe Windows Ultimate 64 bit und 32 GB RAM.
    Der Taskmanager zeigt 2 GB Speicher an beim Absturz.

    Achso - brauch ich auch ne 64 Bit Compilerversion von TCC bzs. LCC?



  • CJens schrieb:

    Ich habe Windows Ultimate 64 bit und 32 GB RAM.

    Das hat überhaupt nichts zu sagen, entscheidend ist der Compiler bzw. dessen erzeugtes Programm.

    CJens schrieb:

    Achso - brauch ich auch ne 64 Bit Compilerversion von TCC bzs. LCC?

    Ja, oder einen anderen 64Bit-fähigen Windows C-Compiler.



  • Wenn du in irgendeinem 32-Bit-Programm auf irgendeiner Plattform 4 GB am Stück reserviert kriegst, bin ich echt beeindruckt. Üblicherweise gehen erstmal 1-2 GB des virtuellen Adressraums für das Betriebssystem drauf, und dann gibt es da noch Threadstacks, dedizierte Bereiche für memory mapping und derlei, und wenn man nicht gerade unter Laborbedingungen arbeitet auch noch Dinge anderer Programmteile auf dem Heap. Dessen freie Bereiche nicht an einem Stück liegen müssen.

    Unter Windows sind in 32-Bit-Prozessen per Default 2GB fürs Betriebssystem reserviert, das ist erstmal der größte Posten (darum schmiert das auch bei 2GB Auslastung ab). Es ist möglich, diesen Anteil auf 1 GB zu verringern, wenn du nicht grad viel mit Grafik machst (ein großer Teil dessen, was im Betriebssystemteil liegt, ist auf den Speicher der Grafikkarte gemappt). Dafür muss Windows mit einem speziellen Schalter gebootet und das Programm mit Support dafür kompiliert werden. Wie das bei TCC und LCC geht, kann ich dir aus dem Stand aber nicht sagen.

    Ansonsten dürfte ein 64-Bit-Compiler helfen, ja.



  • Wutz schrieb:

    CJens schrieb:

    Ich habe Windows Ultimate 64 bit und 32 GB RAM.

    Das hat überhaupt nichts zu sagen, entscheidend ist der Compiler bzw. dessen erzeugtes Programm.

    Na, dann wünsche ich dir viel Spaß dabei, ein 64-Bit-Windows-Programm unter 32-Bit-Windows auszuführen. Oder ein Programm, das 32 GB Speicher braucht, mit weniger. Windows schonmal beim Swappen erlebt?

    Natürlich spielen das Betriebssystem und die vorhandene Menge RAMs eine Rolle. Sie allein reichen nur halt nicht aus.


  • Mod

    seldon schrieb:

    Wenn du in irgendeinem 32-Bit-Programm auf irgendeiner Plattform 4 GB am Stück reserviert kriegst, bin ich echt beeindruckt. Üblicherweise gehen erstmal 1-2 GB des virtuellen Adressraums für das Betriebssystem drauf, und dann gibt es da noch Threadstacks, dedizierte Bereiche für memory mapping und derlei, und wenn man nicht gerade unter Laborbedingungen arbeitet auch noch Dinge anderer Programmteile auf dem Heap. Dessen freie Bereiche nicht an einem Stück liegen müssen.

    Unter Windows sind in 32-Bit-Prozessen per Default 2GB fürs Betriebssystem reserviert, das ist erstmal der größte Posten (darum schmiert das auch bei 2GB Auslastung ab). Es ist möglich, diesen Anteil auf 1 GB zu verringern, wenn du nicht grad viel mit Grafik machst (ein großer Teil dessen, was im Betriebssystemteil liegt, ist auf den Speicher der Grafikkarte gemappt). Dafür muss Windows mit einem speziellen Schalter gebootet und das Programm mit Support dafür kompiliert werden. Wie das bei TCC und LCC geht, kann ich dir aus dem Stand aber nicht sagen.

    Nein. Dem Programm steht sein gesamter Adressraum zur Verfügung, da ist nichts für das Betriebssystem reserviert. Windows reserviert sich 2 GB vom gesamten Arbeitsspeicher, das betrifft den für die einzelnen Prozesse verfügbaren Speicher aber nur indirekt. Außerdem sind die 32-Bit Versionen von Windows künstlich auf 4 GB Gesamtspeicher beschränkt, daher kann man leicht den Eindruck bekommen, dass einem Prozess nur 2GB zur Verfügung stünden. Weil 2GB alles ist, was unter Win32 noch übrig bleibt für Prozesse. Diese werden aber von allen Prozessen geteilt. Wäre mehr Speicher da, könnte jeder Prozess auch mehr benutzen.



  • @ SeppJ:
    Warum empfhiehlst du jedem, nicht umzucasten?

    Manche Compiler erwarten das sogar! Der gcc mault schon rum, wenn ich ein int8_t * nicht auf ein char * umcaste!

    Und wegen so einem umcasten von allokiertem Speicherplatz wird das Programm schon nicht abstürzen.



  • überzeugter Marxist schrieb:

    Warum empfhiehlst du jedem, nicht umzucasten?

    Weil so ein mögliches fehlen von stdlib.h verdeckt wird.

    überzeugter Marxist schrieb:

    Manche Compiler erwarten das sogar! Der gcc mault schon rum, wenn ich ein int8_t * nicht auf ein char * umcaste!

    malloc liefert aber einen void* . Und die sind in C in jeden anderen Zeigertyp konvertierbar. C++-Compiler verlangen den Cast

    überzeugter Marxist schrieb:

    Und wegen so einem umcasten von allokiertem Speicherplatz wird das Programm schon nicht abstürzen.

    Wenn du sonst alles richtig gemacht hast nicht.
    Hier geht es aber um Fehlersuche und darum siehe 1. Antwort.



  • überzeugter Marxist schrieb:

    @ SeppJ:
    Warum empfhiehlst du jedem, nicht umzucasten?

    Manche Compiler erwarten das sogar! Der gcc mault schon rum, wenn ich ein int8_t * nicht auf ein char * umcaste!

    Und wegen so einem umcasten von allokiertem Speicherplatz wird das Programm schon nicht abstürzen.

    void* wurde extra eingeführt damit nicht gecastet werden muss. Denn Casts sollten nur im Ausnahmefall benutzt werden, da sie das Typsystem aushebeln. Das Typsystem ist wichtig weil es viele Fehler findet.

    Ich habe schon gesehen was passieren kann wenn die "Casteritis" um sich greift Zitat: "ich caste alles weil C so Typunsicher ist, deshalb caste ich immer, sonst meckert C weil es den Typ nicht kennt" , "aber irgendwie geht mein Programm nicht" . Es beginnt bei malloc und dann wird plötzlich alles gecastet. Was nicht passt wird passend gecastet!

    char != int8_t



  • SeppJ schrieb:

    Dem Programm steht sein gesamter Adressraum zur Verfügung, da ist nichts für das Betriebssystem reserviert. Windows reserviert sich 2 GB vom gesamten Arbeitsspeicher, das betrifft den für die einzelnen Prozesse verfügbaren Speicher aber nur indirekt.

    Da irrst du dich. Steht übrigens in dem Link über /3GB auch vorne mit dabei. Das ist hier im Detail erklärt. Spoiler: Der Grund ist, dass der Kernel Zugriff auf den Userspace eines Prozesses hat/braucht.

    SeppJ schrieb:

    Außerdem sind die 32-Bit Versionen von Windows künstlich auf 4 GB Gesamtspeicher beschränkt, daher kann man leicht den Eindruck bekommen, dass einem Prozess nur 2GB zur Verfügung stünden. Weil 2GB alles ist, was unter Win32 noch übrig bleibt für Prozesse. Diese werden aber von allen Prozessen geteilt. Wäre mehr Speicher da, könnte jeder Prozess auch mehr benutzen.

    Die künstliche Beschränkung auf 4 GB Phymem (auch mit PAE-Unterstützung) betrifft hauptsächlich die Desktop-Versionen von 32-Bit-Windows; Server-Windows kann da schon seit Windows 2000 mehr, aber sei's drum. Es hat mit dem virtuellen Adressraum wenig zu tun -- Die insgesamt gemappten Pages aller Prozesse können auch dort mehr als 4GB beschreiben, indem eine Swapfile bemüht wird.



  • gary1195 schrieb:

    Ich habe schon gesehen was passieren kann wenn die "Casteritis" um sich greift

    Toll. Ich auch. Ständig.

    gary1195 schrieb:

    Zitat: "ich caste alles weil C so Typunsicher ist, deshalb caste ich immer, sonst meckert C weil es den Typ nicht kennt" , ... Es beginnt bei malloc und dann wird plötzlich alles gecastet. Was nicht passt wird passend gecastet!

    Das ist eine Unsitte aus C++ übernommen, die da ständig rumcasten, weil sie keinen Überblick über ihre Vererbungshierarchie haben bzw. nie hatten; wenn sie denn überhaupt mal Vererbung benutzen.
    In C braucht bzgl. void* bekanntlich überhaupt nicht gecastet zu werden, und es ist noch sehr die Frage (nicht für mich), ob Casting die (Typ)Sicherheit des Programms erhöht.
    Überhaupt sind ausschließliche Zeigercasts in C völlig unnötig, welche mit anschließender sofortiger Dereferenzierung mögen angehen:

    char *x = *(char**)voidp;
    

    Es gibt sogar Fachbücher, die die Notwendigkeit von Casts für die Dokumentation (liebe Kinder, nicht nachmachen) empfehlen:
    http://www.amazon.de/product-reviews/3897212382/ref=cm_cr_pr_hist_1?ie=UTF8&filterBy=addOneStar

    Ich kenne nur einen Anwendungsfall, bei dem in C ein eindimensionaler Zeiger-Cast wirklich notwendig ist, aber den werde ich hier jetzt nicht breittreten.



  • CJens schrieb:

    Achso - brauch ich auch ne 64 Bit Compilerversion von TCC bzs. LCC?

    Die Frage ist auch, brauchst du überhaupt alle Daten gleichzeitig im Speicher?
    Evtl. kannst du dir den 64Bit Eiertanz mit einem Programmumbau ersparen.


  • Mod

    Wutz schrieb:

    Das ist eine Unsitte aus C++ übernommen, die da ständig rumcasten, weil sie keinen Überblick über ihre Vererbungshierarchie haben bzw. nie hatten; wenn sie denn überhaupt mal Vererbung benutzen.

    So ein Quatsch. Das sind in C++ genau so die schlechten Programmierer wie in C. Klingt wie Java in C++, was du beschreibst.

    seldon schrieb:

    SeppJ schrieb:

    Dem Programm steht sein gesamter Adressraum zur Verfügung, da ist nichts für das Betriebssystem reserviert. Windows reserviert sich 2 GB vom gesamten Arbeitsspeicher, das betrifft den für die einzelnen Prozesse verfügbaren Speicher aber nur indirekt.

    Da irrst du dich. Steht übrigens in dem Link über /3GB auch vorne mit dabei. Das ist hier im Detail erklärt. Spoiler: Der Grund ist, dass der Kernel Zugriff auf den Userspace eines Prozesses hat/braucht.

    Entweder reden wir gerade aneinander vorbei oder beide Links bestätigen genau das was ich sage, bis auf das kleine Detail, dass Prozessspeicher wohl auf 2 GB beschränkt ist, nicht 4GB.

    In 32-bit Windows, the total available virtual address space is 2^32 bytes (4 gigabytes). Usually the lower 2 gigabytes are used for user space, and the upper 2 gigabytes are used for system space.

    http://i.msdn.microsoft.com/dynimg/IC535111.png



  • Wenn ich die Betonung mal anders setzen darf:

    In 32-bit Windows, the total available virtual address space is 2^32 bytes (4 gigabytes). Usually the lower 2 gigabytes are used for user space, and the upper 2 gigabytes are used for system space.

    ...dass der virtuelle Adressraum auf einer 32-Bit-Plattform 4 Gigabyte groß ist, ist normal (weil 32-Bit-Zeiger). Das ist auch auf einem 32-Bit-Windows-Server mit 64 GB physikalischem Speicher und PAE so. Unter Windows ist per Default die Hälfte davon für das System reserviert, dem Prozess stehen also noch 2 GB zur Verfügung.

    Das läuft unter Linux übrigens auch nicht anders, nur dass das System da per Default nur 1 GB reserviert. Es wäre auch anders nicht möglich, weil der Kernelcode mit dem Userspace umgehen können muss und es dort ausgesprochen unpraktisch wäre, wenn beispielsweise eine load-Instruction die Daten aus dem Userspace nicht lesen könnte, weil im TLB für die Adresse grad der Systemspeicher steht.



  • SeppJ schrieb:

    So ein Quatsch. Das sind in C++ genau so die schlechten Programmierer wie in C. Klingt wie Java in C++, was du beschreibst.

    Was genauso ein Quatsch ist.

    Herrlich diese Sprachflames 😉


  • Mod

    µ schrieb:

    SeppJ schrieb:

    So ein Quatsch. Das sind in C++ genau so die schlechten Programmierer wie in C. Klingt wie Java in C++, was du beschreibst.

    Was genauso ein Quatsch ist.

    Herrlich diese Sprachflames 😉

    Ich bezog mich auf Wutz' Ansage von Vererbungshierarchien, die so kompliziert sind, dass der Programmierer selber nicht mehr durchblickt. Mag in Java normal sein (habe nicht genug Erfahrung in Java). Aber wenn man jemanden fragt, der das in C++ macht, ist die Rate hier im Forum 100%, dass er von Java kommt.



  • SeppJ schrieb:

    Ich bezog mich auf Wutz' Ansage von Vererbungshierarchien, die so kompliziert sind, dass der Programmierer selber nicht mehr durchblickt. Mag in Java normal sein (habe nicht genug Erfahrung in Java). Aber wenn man jemanden fragt, der das in C++ macht, ist die Rate hier im Forum 100%, dass er von Java kommt.

    Um genau zu sein hat er gesagt, dass ständig gecastet werden muss, weil der Programmierer keinen Überblick mehr hat. Und die Aussage ist eben auch für Java totaler Unsinn.



  • SeppJ schrieb:

    Wutz schrieb:

    Das ist eine Unsitte aus C++ übernommen, die da ständig rumcasten, weil sie keinen Überblick über ihre Vererbungshierarchie haben bzw. nie hatten; wenn sie denn überhaupt mal Vererbung benutzen.

    So ein Quatsch.

    Überhaupt kein Quatsch.
    Gäbe es C++ mit der dortigen Unsitte, sich alles irgendwie zurechtzucasten und das dann auch noch als Typsicherheit zu verkaufen, nicht, würde kein Mensch in C darauf kommen, überhaupt irgendwelche Zeigercasts vorzunehmen.


  • Mod

    Wutz schrieb:

    SeppJ schrieb:

    Wutz schrieb:

    Das ist eine Unsitte aus C++ übernommen, die da ständig rumcasten, weil sie keinen Überblick über ihre Vererbungshierarchie haben bzw. nie hatten; wenn sie denn überhaupt mal Vererbung benutzen.

    So ein Quatsch.

    Überhaupt kein Quatsch.
    Gäbe es C++ mit der dortigen Unsitte, sich alles irgendwie zurechtzucasten und das dann auch noch als Typsicherheit zu verkaufen, nicht, würde kein Mensch in C darauf kommen, überhaupt irgendwelche Zeigercasts vorzunehmen.

    Wegen der vielen Umsteiger von C++ auf C? 🙄

    Das ist in C++ genau so Unsitte wie in C, aber es geht gewiss nicht von C++ aus.



  • Wutz schrieb:

    Überhaupt kein Quatsch.
    Gäbe es C++ mit der dortigen Unsitte, sich alles irgendwie zurechtzucasten und das dann auch noch als Typsicherheit zu verkaufen, nicht, würde kein Mensch in C darauf kommen, überhaupt irgendwelche Zeigercasts vorzunehmen.

    Du hast von C++ noch weniger Ahnung als von C, was?

    In C++-Kreisen gilt Casten als Unsitte und die Verwendung besitzender nackter Zeiger als Steinigungsgrund. Wie du auf die Idee kommst, ausgerechnet Zeigercasts gehörten in C++ zum guten Ton, ist aus meiner Sicht nicht nachvollziehbar. Dagegen gibt es in C übrigens gelegentlich gute Gründe für Pointer-Punning -- hauptsächlich, weil man in C keine generischen Strukturen und keine Vererbung hat. In der Not frisst der Teufel halt Fliegen.

    Was den konkreten Fall angeht: Ob man den Rückgabewert von malloc jetzt castet oder nicht, ist eigentlich Jacke wie Hose. Der Streit ist recht alt; die einen argumentieren, dass man den Code mit Cast sowohl durch einen C- als auch einen C++-Compiler jagen kann, was ggf. eine Portierung vereinfacht, die anderen bemäkelten zu der Zeit, dass der Cast eine gcc-Warnung verdeckte (wenn malloc benutzt wurde, ohne dass der zugehörige Header eingebunden war). Letzteres wurde zwischenzeitlich gefixt, also schlägt die Waage jetzt wohl eher in die Mit-Cast-ist-besser-Richtung, aber letztendlich ist das einer dieser heiligen Nerd-Kriege, in denen man es so oder so sehen kann und es im Endeffekt echt egal ist. Fehler kann man sich damit nicht einhandeln.


  • Mod

    seldon schrieb:

    Fehler kann man sich damit nicht einhandeln.

    Wenn ich mir die nötige Zeit nähme, könnte ich dich auf dutzende Threads hier im Forum verweisen, bei denen der Cast den von dir beschriebenen Programmierfehler verdeckt hat, was dann zu Laufzeitfehlern führte.


Anmelden zum Antworten