Anmelden

Archiv verlassen und diese Seite im Standarddesign anzeigen : Speicherzugriffsfehler mit g++ 3.3.5



newton
26-10-2005, 14:40
Hi,

das folgende Programm produziert einen Speicherzugriffsfehlr, fuer N>723.
//21.10.05
//
using namespace std;

#define N 724 //Matrix Groesse
//N=724 giebt segemtaion fault, N=723 geht noch
#define MAX_SHOWN_LINES 12

#include <iostream>
#include <cmath>

int main(void){

//bilden einer positiven symetrischen Matrix
double aa[N*N];
double aa_sym[N*N];
//matrix zufaellig fuellen
//
double length=N*N;
for(int i=0;i<length;i++){
aa[i]=(double)i;
}
//matrix symmetrisieren
/* for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
double sum=0;
for(int k=0;k<N;k++){
sum+= *(aa+i+k*N) * (*(aa+j+k*N));
//cout<<"sum="<<sum<<endl;
}
*(aa_sym+j + N*i)=sum;
}
} */

}
und zwar mit g++ 3.3.5. (hab das auf 3 verschiedenen Rechnern getestet). Komischerweise passiert das nicht mit g++ 3.3.4 (auf 2 Rechnern getestet).
Kompiliert jeweils mit $g++ -g haupt_programm.cpp
Der Speicherzugriffsfehler passiert auch nicht, wenn ich die zweite Array deklaration ausklammere oder die Groesse auf N beschraenke (double aa_sym[N*N]; ).
gdb giebt mir folgendes:

Breakpoint 1, main () at haupt_programm.cpp:21
21 double length=N*N;
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x080485cd in main () at haupt_programm.cpp:21
21 double length=N*N;
(gdb) n

Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.

Was mich wundert, ist das der Fehler von der Groesse abhaengt. Und so besonders gross ist das ja nicht (~4MB), das sollte in 1GB Speicher reinpassen ;)

Sieht jemand den Fehler? Oder ist das ein Bug vom gcc?
Ich hab das Programm mal angehaengt, zum ausprobieren. Die Kommentare sind teilweise nicht mehr ganz richtig, es ist ein Ausschnitt aus einem Programm zum loesen linearer Gleichungssysteme.

Gruss,
newton

Boron
26-10-2005, 15:35
Wird da eventuell die maximale Stackgröße überschritten?

Vielleicht solltest du deine Tabellen auf dem Heap anlegen:
double* aa = new double[N*N];
double* aa_sym = new double[N*N];

Ach ja:
Wenn schon C++, dann auf Makros verzichten (steht im Stroustrup so drin):
const unsigned N 724;
const unsigned MAX_SHOWN_LINES 12;

newton
26-10-2005, 16:14
Wird da eventuell die maximale Stackgröße überschritten?
Hm, hatte ich auch schon ueberlegt, aber waere schon komisch, wenn das von gcc 3.3.4 zu 3.3.5 sich geaendert (verkleinert!) haette, oder? 1 Mio Array Elemente erscheint mir auch nicht so gross.
Und vor allem, wenn ich nur _ein_ N*N array definiere, klappt das ja. Also kanns imho nicht die maximale Stackgroesse sein. Oder giebt es sowas wie maximalen Speicher pro programm?

Vielleicht solltest du deine Tabellen auf dem Heap anlegen:
double* aa = new double[N*N];
double* aa_sym = new double[N*N];
Das funktioniert, vielen Dank! :)
Aber kannst Du mir den Unterschied erklaeren?

Wenn schon C++, dann auf Makros verzichten (steht im Stroustrup so drin)
Hat das technische Gruende, oder ist das mehr so eine Stilfrage?

Gut, jetzt hab ich also einen Workaround, aber das eigentliche Problem noch nicht geloest. Wiso haengt das Auftauchen des Speicherzugriffsfehlers von der Array laenge bzw. der Anzahl der Arrays ab? Und wiso taucht das Problem bei ner anderen Compilerversion nicht auf? (waren uebrigen auch zwei verschiedene distries: gcc 3.3.4 auf ner suse 9.2, und gcc 3.3.5 auf debian 3.1)

newton :confused:

Joghurt
26-10-2005, 18:17
1 Mio Array Elemente erscheint mir auch nicht so gross.1 Mio doubles, und das zweimal, macht 16MB Stack. Finde ich schon viel.


Hat das technische Gruende, oder ist das mehr so eine Stilfrage?Mehr Stil. Bei defines kann der Compiler keine Überprüfung vornehmen, da er ja gar nichts sieht. consts sind schon besser und belegen ebenfalls keinen Speicherplatz. Außerdem kommt einem die Präprozessorersetzung nicht mehr in die Quere:
#define A 3+4
const int B=3+4;
int c = A*2; // = 11 (falsch! Man hätte #define A (3+4) schreiben müssen)
int d = B*2; // = 14

newton
27-10-2005, 08:17
Bei defines kann der Compiler keine Überprüfung vornehmen, da er ja gar nichts sieht.
Ich dachte, zuerst kommt der preprocessor, der nimmt die ersetzungen der defines vor (und loescht die Kommentare), und giebt das dann weiter an den Compiler. Der Compiler wuerde dann ja durchaus sehen, was mittels define ersetzt wurde. Oder?

Joghurt
27-10-2005, 10:44
Nö.

Schreib mal ein kleines Programm mit ein paar Defines (und am besten ohne includes) und mache gcc -E datei.c. Das ist das, was der Compiler vom Präprozessor bekommt.

Beispiel:
#define A 2+3
main() { int x = A*4; }{ bekommt der Compiler als
main() { int x = 2+3*4;}