Net-srac Geschrieben 30. Oktober 2002 Geschrieben 30. Oktober 2002 Tachchen, ich hab 1 Methode, die als parameter einen integer übergeben bekommt. Nun hatte ich vor einen array zu erzeugen, der der größe dieses integer entspricht. Ich bekomm nur immer einen Kompilerfehler, das ein konstanter Wert erwartet wird?! Was mach ich falsch? Oder geht das in C++ nicht? bool dynIP::connect(int count_ip) { .... int lSocket[count_ip]; .... [/PHP] Zitieren
Orffi Geschrieben 30. Oktober 2002 Geschrieben 30. Oktober 2002 Es ist kein Standard, wenn man die Größe eines Arrays nicht mit einem konstantem Ausdruck angibt. Der gcc erlaubt dies, aber wie gesagt es ist kein Standard und Dein Compiler erlaubt es, wie Du gemerkt hast auch nicht. Dies tut er zurecht. Trotzdem gibt es eine Lösung für Dich. In C++ gibt es das Schlüsselwort new. Mit diesem kannst Du dynamisch Arrays anlegen. int *array = new int[deineGewuenschteGroesse] Was ich fast vergessen hätte: Natürlich muß der Speicher auch wieder freigegeben werden. dies tut man am besten mit delete[] array. HTH Jan Zitieren
nic_power Geschrieben 30. Oktober 2002 Geschrieben 30. Oktober 2002 Originally posted by Net-srac bool dynIP::connect(int count_ip) { .... int lSocket[count_ip]; .... Das geht nicht. Da die Groesse des Arrays zur Compilezeit nicht bekannst ist, musst Du es in diesem Fall dynamisch erzeugen (new, malloc). Nic Zitieren
Crush Geschrieben 30. Oktober 2002 Geschrieben 30. Oktober 2002 "Der gcc erlaubt dies" Würd mich interessieren, wie der GCC das macht. Zitieren
fmarx2000 Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by Crush "Der gcc erlaubt dies" Würd mich interessieren, wie der GCC das macht. Würde mich auch brennend interessieren, schließlich ist ja die Größe zur Compilezeit nicht bekannt , nimmt er dann 1 an oder wie ?? Frank Zitieren
nic_power Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by nic_power Das geht nicht. Da die Groesse des Arrays zur Compilezeit nicht bekannst ist, musst Du es in diesem Fall dynamisch erzeugen (new, malloc). Ich habe gerade nochmal nachgesehen, es geht doch . Nach ISO C99 ist dies erlaubt und wird auch vom gcc unterstuetzt. Es gibt allerdings ein paar Unterschiede zu "normalen" Arrays. Der Speicherplatz wird an der Stelle der Deklaration allokiert. Der Speicher wird freigegeben, sowie man den Scope verlaesst. Naeheres im gcc Manual: http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Length.html#Variable%20Length Nic Zitieren
fmarx2000 Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by nic_power Ich habe gerade nochmal nachgesehen, nach ISO C99 ist dies erlaubt und wird auch vom gcc unterstuetzt. Es gibt allerdings ein paar Unterschiede zu "normalen" Arrays. Der Speicherplatz wird an der Stelle der Deklaration allokiert. Der Speicher wird freigegeben, sowie man den Scope verlaesst. Nic Wenn aber die Größe des Arrays zur Compilezeit nicht bekannt ist ( die Größe ist ja in diesem Fall ein formaler Funktionsparameter) wie groß ist dann das Array das vom Compiler angelegt wird ? Oder wird das dann intern mittels eines malloc oder new gelöst ? Frank Zitieren
nic_power Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by fmarx2000 Wenn aber die Größe des Arrays zur Compilezeit nicht bekannt ist ( die Größe ist ja in diesem Fall ein formaler Funktionsparameter) wie groß ist dann das Array das vom Compiler angelegt wird ? Oder wird das dann intern mittels eines malloc oder new gelöst ? Frank Koennte man vermuten, ist aber nicht der Fall. Der notwendige Speicherplatz wird zur Laufzeit auf dem Stack beschafft (wie auch der Speicherplatz fuer jede andere Variable die innerhalb einer Funktion oder eines Funktionsblockes deklariert wird). Falls Interesse besteht, wuerde ich mal ein passendes Beispiel raussuchen. Nic Zitieren
fmarx2000 Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by nic_power Koennte man vermuten, ist aber nicht der Fall. Der notwendige Speicherplatz wird zur Laufzeit auf dem Stack beschafft (wie auch der Speicherplatz fuer jede andere Variable die innerhalb einer Funktion oder eines Funktionsblockes deklariert wird). Falls Interesse besteht, wuerde ich mal ein passendes Beispiel raussuchen. Nic Ahh so, d.h. es verält sich wie eine automatische Variable nur wird das ganze eben dann mit variabler Größe auf dem Stack abgelegt. Ich finde das Feature nicht so toll, Stacks sind ja in der Regel nicht so gross und um sich etwas kompfort zu erkaufen kann man sich schnell ins Knie schiessen. Eine saubere Lösung mit new und delete [] fände ich da besser. Frank Zitieren
nic_power Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by fmarx2000 Ahh so, d.h. es verält sich wie eine automatische Variable nur wird das ganze eben dann mit variabler Größe auf dem Stack abgelegt. Ich finde das Feature nicht so toll, Stacks sind ja in der Regel nicht so gross und um sich etwas kompfort zu erkaufen kann man sich schnell ins Knie schiessen. Stacks werde im Allgemeinen nur durch die Groesse des Verfuegbaren Speichers bzw. irgendwelche Kernelvariablen beschraenkt ("maxssize" bei HPUX beispielsweise). Nic Zitieren
fmarx2000 Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by nic_power Stacks werde im Allgemeinen nur durch die Groesse des Verfuegbaren Speichers bzw. irgendwelche Kernelvariablen beschraenkt ("maxssize" bei HPUX beispielsweise). Nic Komisch ich dachte Heaps sind das, die werden doch durch die Größe des Hauptspeichers beschränkt. Ich habe das noch so in Erinnerung das uns unser Prof. immer vor zu tiefen Rekursionen gewarnt hat weil dann der Stack in den Heap wachsen kann. Ist auch egal, ich finde des trotzdem nicht gut. Frank Zitieren
Klotzkopp Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by nic_power Stacks werde im Allgemeinen nur durch die Groesse des Verfuegbaren Speichers bzw. irgendwelche Kernelvariablen beschraenkt ("maxssize" bei HPUX beispielsweise). Unter Windows wird die Stackgröße ins Binary hineinkompiliert und ist damit durchaus beschränkt. Gibt es wirklich Systeme, bei denen eine simple rekursive Endlosschleife den kompletten Speicher frisst? Zitieren
Orffi Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Als ich erwähnte, daß der gcc die Größenangabe als Variable erlaubt, wollte ich damit nicht sagen, daß ich es gut finde. Ich persönlich mag es auch nicht und würde es auch nie benutzen. Auch nicht, wenn ich speziell für gcc entwickeln würde. Auch finde ich es nicht gut, daß dieses Verhalten Einzug in den C99 Standard gehalten hat. Es ist aber definitiv kein Standard von C++. Wie schon weiter oben erwähnt wurde ist die schönste und sauberste Methode, wenn man mit new und delete arbeitet. Jan Zitieren
Net-srac Geschrieben 31. Oktober 2002 Autor Geschrieben 31. Oktober 2002 ... und genau so hab ich es auch gemacht... danke nochmal Zitieren
nic_power Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by Klotzkopp Unter Windows wird die Stackgröße ins Binary hineinkompiliert und ist damit durchaus beschränkt. Gibt es wirklich Systeme, bei denen eine simple rekursive Endlosschleife den kompletten Speicher frisst? Theoretisch ja, praktisch nein. Unixoide Systeme kontrollieren die maximale Groesse des Stacksegments ueber eine Variable, die vom Nutzer gesetzt werden kann. Erreicht die Groesse des Stacks den Wert der Variablen generiert der Kernel für den betroffenen Prozess einen Core-Dump mit einer entsprechenden Fehlermeldung. Nic Zitieren
nic_power Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by Orffi Als ich erwähnte, daß der gcc die Größenangabe als Variable erlaubt, wollte ich damit nicht sagen, daß ich es gut finde. Ich persönlich mag es auch nicht und würde es auch nie benutzen. Auch nicht, wenn ich speziell für gcc entwickeln würde. Auch finde ich es nicht gut, daß dieses Verhalten Einzug in den C99 Standard gehalten hat. Es ist aber definitiv kein Standard von C++. Wie schon weiter oben erwähnt wurde ist die schönste und sauberste Methode, wenn man mit new und delete arbeitet. Jan Du solltest aber nicht ausser acht lassen, das new und delete deutlich mehr Zeit kosten, da es sich hier um eine komplette Speicherverwaltung handelt. Speicher auf dem Stack kostet "zeitmaessig" fast nichts, da man nur den Stackpointer entsprechend anpassen muss. D.h. bei Funktionen mit kleinen Arrays, die sehr haeufig aufgerufen werden, kann diese Methode unter Umstaenden deutlich schneller sein (und ist obendrein noch mit Null Aufwand zu implementieren). Ich persoenlich wuerde aber auch eher dazu tendieren, mit den Speicher auf "klassische" Weise zu besorgen. Nic Zitieren
nic_power Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 So, und hier noch ein Beispiel mit Kommentaren, wie der gcc das folgende Programm umsetzt. Uebrigens auch ein sehr schoenes Beispiel fuer die Komplexitaet moderner CPUs (siehe auch Diskussion um das "Fachinformatiker-OS". int main(int argc, char **argv) { func(atoi(argv[1])); } int func(int size) { int array[size]; printf("Array Size = %d Bytes\n", size); } main: # int main(int argc, char **argv) # { # /* Defaultstack Anlegen */ save %sp, -112, %sp # /* %i0 enthaelt pointer auf argv */ # /* %i0+4 zeigt demnach auf den ersten Übergabearameter */ # int tmp=atoi(argv[1]); call atoi, 0 # /* %o0 ist Übergabeparameter an die Funktion "atoi()" */ # /* das Laden des Parameter (argv[1]) erfolgt im Delayslot */ ld [%i1+4], %o0 # /* das Ergebnis (tmp) wird ins register %o0 geschrieben */ # /* Aufruf unserer Funktion */ # func(tmp); /* entspricht func(atoi(argv[1])) */ call func, 0 # /* aufraeumen und Programmende */ # } restore %g0, %o0, %o0 nop _string: .asciz "Array Size = %d Bytes\n" func: # int func(int size) # { # /* size wird in register %i0 übergeben (%o0 beim Aufrufer) */ # /* Defaultstack Anlegen */ save %sp, -112, %sp # int array[size]; # /* da ein "int" 4 byte gross ist, muss fuer */ # /* 4*size Bytes Platz auf dem Stack geschaffen werden */ # int tmp=4*size; /* entspricht %o4=4*%i0 */ sll %i0, 2, %o4 # int arg01=size; # /* %o1=%i0, %o1 enthaelt jetzt die Groesse des Arrays also size */ mov %i0, %o1 # /* SPARC-V9 Architekturen arbeiten mit Stacks auf 8 Byte */ # /* boundaries, die folgenden Anweisungen erledigen das */ # /* entsprechende Alignment, als Ergebnis steht in reg %o2 */ # /* Die Anzahl der auf dem Stack benötigten Bytes */ add %o4, 7, %o3 mov %sp, %i0 and %o3, -8, %o2 # /* erste Haelfte der Adresse von String nach %g1 laden */ sethi %hi(_string), %g1 # /* Stackpointer anpassen, damit ist für "size" Bytes Platz auf */ # /* dem Stack */ sub %sp, %o2, %sp # printf(string, size); /* printf("Array Size = %d Bytes\n", size); */ # /* erste parameter an printf in %o0, zweiter parameter in %o1 */ call printf, 0 # /* zweite Haelfte der Adresse des Strings mit %g1 verknuepfen */ # /* und das Ergebnis nach %o0 schreiben, wird vor dem Call printf */ # /* ausgefuehrt */ or %g1, %lo(_string), %o0 mov %i0, %sp nop # /* zurueck zum aufrufer */ ret # /* und vorher den Stack wiederherstellen */ restore Zitieren
fmarx2000 Geschrieben 31. Oktober 2002 Geschrieben 31. Oktober 2002 Originally posted by nic_power Theoretisch ja, praktisch nein. Unixoide Systeme kontrollieren die maximale Groesse des Stacksegments ueber eine Variable, die vom Nutzer gesetzt werden kann. Erreicht die Groesse des Stacks den Wert der Variablen generiert der Kernel für den betroffenen Prozess einen Core-Dump mit einer entsprechenden Fehlermeldung. Nic Ich denke auch mal das es unter NT auch wie unter UNIX ist dass jeder Prozess einen bestimmten Speicher als Stack bekommt und nicht den gesamten Systemspeicher, was dann doch schon eine Einschränkung ist. Wenn ich eine Rekursion nur lange genug ausführe kommt es zum überlauf da ja ständig Zeug auf den Stack gelegt wird aber es nicht mehr runtergeholt wird. Frank Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.