Beschraenkung der Array-Groesse in C++

Persönliche Seite #3059091
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)
Persönliche Seite #3059106
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];
Persönliche Seite #3059142
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?
Persönliche Seite #3060172
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?
Gast #3060439
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.
Gast #3060505
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
Gast #3061769
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.
Gast #3061837
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
#3069353
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
#3069358
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren