Forum: PC-Programmierung Beschraenkung der Array-Groesse in C++


von Maxim (maxim) Benutzerseite


Lesenswert?

Ich benoetige ein float-Array der Dimension [64][64][64][3][3], bekomme 
aber "segmentation fault". Mit z.B. [64][64][32][3][3] gibt es keine 
Probleme.

Wie kann man diese Beschraenkung umgehen? (64-Bit-Linux mit 8 GB RAM)

von Peter II (Gast)


Lesenswert?

Maxim S. schrieb:
> Ich benoetige ein float-Array der Dimension [64][64][64][3][3], bekomme
> aber "segmentation fault". Mit z.B. [64][64][32][3][3] gibt es keine
> Probleme.

ein segmentation kommt aber nicht von einem Array. Wo tritt der fehler 
genau auf? Oder Versucht du das array auf dem Stack anzulegen?

von Thorsten (Gast)


Lesenswert?

Zeig mal den kompletten Code im Kontext. Im Prinzip sollte das gehen.

von Maxim (maxim) Benutzerseite


Lesenswert?

Peter II schrieb:
> Maxim S. schrieb:
>> Ich benoetige ein float-Array der Dimension [64][64][64][3][3], bekomme
>> aber "segmentation fault". Mit z.B. [64][64][32][3][3] gibt es keine
>> Probleme.
>
> ein segmentation kommt aber nicht von einem Array. Wo tritt der fehler
> genau auf? Oder Versucht du das array auf dem Stack anzulegen?

Ja, ich lege es auf dem Stack an. Allerdings nur, weil ich nicht 
wirklich weiss, wie man es auf dem Heap anlegt. Es muss auf jeden Fall 
ein zusammenhaengender Speicherbereich sein.

Thorsten schrieb:
> Zeig mal den kompletten Code im Kontext. Im Prinzip sollte das gehen.

Diese Zeile fuehrt zu segmentation fault:
1
float theArray[64][64][64][3][3];

von g457 (Gast)


Lesenswert?

> weil ich nicht wirklich weiss, wie man es auf dem Heap anlegt

new [] regelt.

von Thorsten (Gast)


Lesenswert?

Mehr Kontext. Auf dem Stack könnte das schon problematisch werden, je 
nach eingestelltem Stack Limit.

von Peter II (Gast)


Lesenswert?

Maxim S. schrieb:
> Ja, ich lege es auf dem Stack an. Allerdings nur, weil ich nicht
> wirklich weiss, wie man es auf dem Heap anlegt.

dann solltest du eventuell erstmal anfangen C zu lernen.- Auf dem Stack 
legt man nicht so viele Daten an.

von Maxim (maxim) Benutzerseite


Lesenswert?

Ich denke, ich werde aus dem [64][64][64][3][3]-Array einfach neun 
[64*64*64]-Arrays machen, die jeweils fuer sich zusammenhaengend im 
Speicher liegen muessen, was ja mit new gehen sollte.

von Peter II (Gast)


Lesenswert?

Maxim S. schrieb:
> Ich denke, ich werde aus dem [64][64][64][3][3]-Array einfach neun
> [64*64*64]-Arrays machen, die jeweils fuer sich zusammenhaengend im
> Speicher liegen muessen, was ja mit new gehen sollte.

das andere muss auch mit new gehen.

von Maxim (maxim) Benutzerseite


Lesenswert?

Peter II schrieb:
> Maxim S. schrieb:
>> Ich denke, ich werde aus dem [64][64][64][3][3]-Array einfach neun
>> [64*64*64]-Arrays machen, die jeweils fuer sich zusammenhaengend im
>> Speicher liegen muessen, was ja mit new gehen sollte.
>
> das andere muss auch mit new gehen.

So, dass ich neun zusammenahengende Speicherbereiche der Groesse 64^3 
habe?

von Peter II (Gast)


Lesenswert?

Maxim S. schrieb:
> So, dass ich neun zusammenahengende Speicherbereiche der Groesse 64^3
> habe?

das sollte auch gehen, aber das ganze geht auch als ein speicherbereich. 
Es sind doch nur 18Mbyte. Dafür braucht man auch kein 64bit system. Das 
ganze passt nur nicht auf den Stack. Im Heap ist das doch kein Thema.

von Thorsten (Gast)


Lesenswert?

Wenn die neun 64^3 Arrays gleichzeitig auf dem Stack liegen, fliegt dir 
das Ganze wieder um die Ohren.

von g457 (Gast)


Lesenswert?

> So, dass ich neun zusammenahengende Speicherbereiche der Groesse 64^3
> habe?

Kannst auch einen großen machen. new[] regelt immernoch.

von Brater (Gast)


Lesenswert?

Kleiner Tipp: Cramersche Regel für Arrays. Dann braucht man nicht diese 
abartigen vielen Klammern.

von Maxim (maxim) Benutzerseite


Lesenswert?

Hier mein Lösungansatz:
1
#include <iostream>
2
3
using namespace std;
4
5
class Helper {
6
public:
7
  Helper(int Nz_, int Ny_, int Nx_);
8
  int index(int k, int j, int nz, int ny, int nx);
9
  void print(float *data);
10
11
private:
12
  int Nz, Ny, Nx;
13
};
14
15
Helper::Helper(int Nz_, int Ny_, int Nx_) {
16
  Nz = Nz_;
17
  Ny = Ny_;
18
  Nx = Nx_;
19
}
20
21
int Helper::index(int k, int j, int nz, int ny, int nx) {
22
  return nx + Nx*(ny + Ny*(nz + 2*(j + 3*k)));
23
}
24
25
void Helper::print(float *data) {
26
  cout << "start address: " << data << endl;
27
  cout << "first value: " << data[0] << endl;
28
  cout << "last value: " << data[Nz*Ny*Nx - 1] << endl << endl;
29
}
30
31
int main(void) {
32
  int Nz = 64, Ny = 64, Nx = 64;
33
  int size = Nz*Ny*Nx*3*3;
34
  int index;
35
  float *a = new float[size];
36
  Helper h = Helper(Nz, Ny, Nx);
37
38
  for(int i = 0; i < size; i++) {a[i] = i;}
39
  
40
  for(int i = 0; i < 9; i++) {h.print(a + i*Nz*Ny*Nx);}
41
}

Das ist natürlich nur ein Beispiel. Im eigentlichen Quellcode soll eine 
Funktion (FFT-Bibliothek) die neun Nz*Ny*Nx großen Blöcke nacheinander 
bekommen und verarbeiten. Das habe ich in diesem Beispiel mit der 
Funktion Helper::print() simuliert. Ist das alles programmiertechnisch 
sauber?

von Sven B. (scummos)


Lesenswert?

Die maximale Stack-Größe kannst du mit "ulimit -a" nachgucken. Rechne 
doch mal, ob du die überschreitest -- ich schätze schon, bei dem 
Riesen-Array.

Wie schon erwähnt wurde legt man sowas nicht auf dem Stack an.

von W.S. (Gast)


Lesenswert?

Maxim S. schrieb:
> float theArray[64][64][64][3][3];

Hmm.. wenn ich mich recht erinnere, dann kann C keine mehrdimensionalen 
Felder. Stattdessen sieht das so aus:

theArray = [64 pointer], die jeweils auf folgendes zeigen:

---> array[64 pointern], die jeweils auf folgendes zeigen:

---> array[64 pointern], die jeweils auf folgendes zeigen:

---> array[3 pointern], die jeweils auf folgendes zeigen:

---> array[3 floats].

Du solltest besser 1 Array definieren:

float theArray[64*64*64*3*3];

und deine Zugriffslogik selber organisieren. Alternativ kannst du 
FreePascal nehmen, denn Pascal kann nativ mehrdimensionale Felder.

W.S.

von Peter II (Gast)


Lesenswert?

W.S. schrieb:
> Hmm.. wenn ich mich recht erinnere, dann kann C keine mehrdimensionalen
> Felder. Stattdessen sieht das so aus:

dann erinnerst du dich falsch. Das geht ohne Probleme in C. er macht 
dann das gleich wie du manuell machen willst.

von Steffen (Gast)


Lesenswert?

Wenn Du nur das Stack-Problem hast, und Du auch nur eine Instanz des 
Arrays im lokalen Funktionsbereich benutzt, dann ist die "einfachste" 
Lösung:

static float array[64][64][64][3][3] ;

Damit bist Du wieder im (nicht initailisierten) Datensegment, anstatt 
auf dem Stack. Oder einfach global deklarieren.

Ansonsten, die Idee mit der Indizierung über eine (Hilfs-)klasse sieht 
gut aus! Mach es doch konsequent und lass die Klasse auch gleich die 
Größe des Arrays zurückgeben. Oder ganz konsequent und die Klasse das 
Array  verwalten. Achja, bei Deiner index Methode statt "...+2*(j+3*k)" 
besser "...+3*(j+3*k)"?

Über const, size_t, c'tor Initialisierung etc. lass ich mal nicht aus: 
Das ist eher Schönheitswettberwerb... ^^ Vielleicht noch der Hinweis auf 
boost: 
http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/user.html. Das 
ist in Deinem Fall aber wohl überdimensioniert. ^^

Grüße, Steffen

von W.S. (Gast)


Lesenswert?

Peter II schrieb:
> dann erinnerst du dich falsch. Das geht ohne Probleme in C. er macht
> dann das gleich wie du manuell machen willst.

Huch? Was für eine seltsame Argumentation deinerseits. Also hab ich mich 
doch richtig entsonnen: C kann keine mehrdimensionalen Felder, 
stattdessen werden daraus Felder von Pointern auf Felder von Pointern 
auf Felder von Pointern.... draus.

Und nochwas : ICH will sowas überhaupt nicht manuell machen, sondern hab 
nur das mal explizit dargestellt, was bei C aus so einer Deklaration 
entsteht. Also lies bitte etwas gründlicher.

W.S.

von BoeserFisch (Gast)


Lesenswert?

W.S. schrieb:
> Huch? Was für eine seltsame Argumentation deinerseits. Also hab ich mich
> doch richtig entsonnen: C kann keine mehrdimensionalen Felder,
> stattdessen werden daraus Felder von Pointern auf Felder von Pointern
> auf Felder von Pointern.... draus.

STOP!
Natürlich kann C mehrdimensionale Felder.
Und auch Pointer auf Felder, wenn man's entsprechend deklariert. Kommt 
mir bloss nicht mit Hinterlassenschaften wie Pascal.
Es soll offensichtlich immer noch rudimentäre (nicht ANSI-fähige) 
Compiler geben, die obigen Käse produzieren. Im Zweifelsfall vor dem 
voreiligen Posten: Einfach mal den Disassembler anschmeissen.

Zum eigentlichen Problem: die mehrdimensionale Indizierung erzeugt u.U. 
sehr ineffizienten Code, und zwar meist so, wie wenn man die Indizierung 
von Hand rechnet (d.h. (x0, .., xn) -> Speicheradresse). Einer hat schon 
den "Cramer" eingeworfen...

- Boeserfisch

von Oliver J. (skriptkiddy)


Lesenswert?

Brater schrieb:
> Kleiner Tipp: Cramersche Regel für Arrays. Dann braucht man nicht diese
> abartigen vielen Klammern.
Kannst du das bitte genauer erklären. Habe ich noch nie gehört und auch 
nichts dazu im Netz gefunden. Mir ist natürlich klar, was die Cramersche 
Regel ist, aber wie man sie auf Arrays anwenden kann ist mir unklar.

Gruß Oliver

von (prx) A. K. (prx)


Lesenswert?

W.S. schrieb:
> stattdessen werden daraus Felder von Pointern auf Felder von Pointern
> auf Felder von Pointern.... draus.

Ist mir bei normal deklarierten Arrays noch nicht untergekommen.

> C kann keine mehrdimensionalen Felder

Formal syntaktisch nicht, weil es sich in C anders als in Pascal um 
verschachtelte eindimensionale Arrays handelt. Aber trotzdem werden im 
Speicher keine Pointer abgelegt und in der Praxis ist der Unterschied 
bei letztlicher Operation mit Skalaren wirklich nur syntaktischer Natur.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.