On Sun, 29 Jun 2003 17:11:42 +0200 (CEST)
Achim Fritz <[EMAIL PROTECTED]> wrote:

> Hi,
> 
> fuer ein Finite-Element-Programm in C, muesste ich unbedingt mehr als 2Gb
> Speicher allokieren. Der Rechner hat 2Gb Speicher und 2Gb Swap.

du kannst nicht mehr als 4GB Speicher allokieren da der pointer datentyp 32Bit ist 
(auf 32Bit Maschinen).
(void*) zum beispiel.

es ist auch nicht moeglich, mehrere 4GB bereiche zu allokieren, da in C der gesamte
allokierte Speicherbereich über Pointer zugänglich sein muss.

gleichwohl mag linux insgesamt mehr als 4GB RAM verwalten, so dass einzelne Prozesse
(nicht Threads!) jeweils die 4GB erreichen können.

> Ich habe erst gedacht, es liegt am Kernel (CONFIG_HIGHMEM ist gesetzt),
> habe jetzt aber festgestellt, dass es nicht moeglich ist in C eine Integer
> zu deklarieren, die groesser als 2^31 ist.

zunächst einmal

#include <sys/types.h>

und dann:

u_int32_t
int32_t

usw. verwenden statt int und long long. sonst ist dein code nicht portabel.
datentypen wie int und long etc. sind per definition eine sünde und jede
programmiersprache die sie besitzt ist murx.

ausnahme zum beispiel das gute alte lisp, wo der datentyp int seinem
namen gerecht wird und _beliebig_ grosse zahlen aufnehmen kann.

doch zurueck zum thema, du musst also zunaechst einmal klarstellen, welche
datentypen du verwenden moechtest. jetzt zu deinem problem mit der zuweisung:

u_int32_t x = 4294967295;

--> mist.c:5: warning: decimal integer constant is so large that it is unsigned

das problem ist hier, dass der compiler die symbole zunaechst einmal einzeln parst.
er sieht eine ziffernfolge: "234879" und macht daraus ein Integer Symbol,
also eine Konstante vom Datentyp "int". Je nach compiler und platform ergeben
sich daraus unterschiedliche limitierungen. bei einer 32bit maschine ist zum beispiel
2147483647 der groesstmoegliche wert. bei einer 16bit maschine ist es halt 32767.
dass du das hier in eine variable zuweisst, die den wert aufnehmen kann ist zu dem
zeitpunkt unbekannt. der compiler sieht einfach diese zahl und will sie einlesen.
ergo musst du ihm sagen, dass es sich hierbei um eine grosse zahl handelt:

u_int32_t x = 4294967295u;

siehst du das u am ende der zahl? das steht fuer unsigned. er soll also hier keinen
int lesen, sondern einen unsigned int. dann klappts auch, weil der wert da reinpasst.
das problem geht aber noch weiter:

u_int64_t y = 2999999999999u;

mist.c:6: integer constant out of range

das ding passt eben nicht in einen unsigned int. zumindest nicht auf einer
32bit maschine! also musst du machen:

u_int64_t y = 2999999999999ll;

ll steht fuer long long. ja richtig, der grosse mist mit unportablen datentyp-
groessenangaben setzt sich hier leider fort und alles ist wieder unportabel.
wenigstens kriegst du compiler errors wenn du das suffix hinten nicht richtig gemacht
hast.

wenn du jetzt an das limit vorzeichenloser 64 bit zahlen faehrst:

u_int64_t oo=18446744073709551615ll;

--> mist.c:7: warning: decimal integer constant is so large that it is unsigned

musst du eben das u wieder dazu machen:

u_int64_t oo=18446744073709551615ull;


das gesamte integer handling ist kacke in C und in den meisten anderen sprachen leider 
auch.


> Hab schon mehrere Compiler ausprobiert (unter anderem auch Borland auf
> Windows) und in den manpage von gcc nach optionen gesucht.
> (2.4.21 hab ich auch schon getestet)

es ist unabhaengig vom compiler. C ist so definiert.

> Der Kernel hat auch keine Probleme mit grossen Zahlen:
> [EMAIL PROTECTED]:~/ugspeicher/test-proc> echo "2^31"|bc
> 2147483648
> [EMAIL PROTECTED]:~/ugspeicher/test-proc> echo "2^32"|bc
> 4294967296
> [EMAIL PROTECTED]:~/ugspeicher/test-proc> echo "2^100"|bc
> 1267650600228229401496703205376

das hat nichts mit dem kernel zu tun. bc ist ein programm,
und das kann es halt.

> Hat jemand ne Ahnung, oder ne Idee?

jep. probier mal:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  void *buf = malloc ( (size_t) (3000000000u) ); // genau 3 GB
  if (buf==0) printf("oh no\n"); else printf("yeah\n");
  return 0;
};


du musst denke ich deinen algorithmus gruendlich ueberdenken und mittels 
zwischenspeichern auf festplatte
den speicherbedarf __drastisch__ reduzieren.

das daemliche unix 32-bit design in verbindung mit der diesbezueglich ziemlich 
daemlichen Sprache C
erbringt uns derzeit das naechste grosse problem der art wie sie schon so oft da war. 
man denke nur
an das alte MS-DOS mit expanded memory, extended memory, hi memory area, 64kb offset 
size und 16bit pointer
sowie dem pseudo 32bit pseudo seg+offs pointermist.

erste auslaeufer sind erkennbar mit den sogenannten large-files. sie koennen groesser 
als 2GB sein.
man muss seine programme entsprechend umprogrammieren, damit sie mit solchen dateien 
umgehen koennen.

der naechste mist ist schon vorprogrammiert. bei 128bit maschinen gibt es dann 
large-large files.
besonders sinnvolle namensgebung uebrigens.

MfG
Erik

-- 
Erik Thiele


--
Haeufig gestellte Fragen und Antworten (FAQ):
http://www.de.debian.org/debian-user-german-FAQ/

Zum AUSTRAGEN schicken Sie eine Mail an [EMAIL PROTECTED]
mit dem Subject "unsubscribe". Probleme? Mail an [EMAIL PROTECTED] (engl)

Antwort per Email an