Erreur de segmentation ...

Résolu/Fermé
martiennette Messages postés 2 Date d'inscription mercredi 23 janvier 2008 Statut Membre Dernière intervention 24 janvier 2008 - 23 janv. 2008 à 16:17
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 - 24 janv. 2008 à 10:19
Bonjour,
j'écris un petit programme en C pour lire un fichier binaire très volumineux, qui contient un vecteur très long, et le transformer en matrice 3 D.

Tou se passe bien jusqu'à ce que je m'attaque à des vraiment gros fichiers, typiquement, quand je depasse environ 500 000 lignes (quand le paramètre nslice depasse 10, et donc le nombre total de ligne pass au dessus de 456020).

Est ce qu'il y a une limite de taille quelque part, que je ne vois pas ?
je ne vois pas où ça bloque...

Merci d'avance

marie

le programme:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <cstdio>
using namespace std;

#define ncar 151
#define nslice 10

int main()
{

// Indices pour trier data
long int i,j,xi,yi,si,s;
long int Ndatatot;

// Données sur le format du fichier

int NdataR,NdataC;
NdataR=NdataC=ncar*ncar;
Ndatatot=ncar*ncar*nslice*2;

cout << "Ndatatot : " << Ndatatot << endl;

double data[ncar*ncar*nslice*2]={0};

double dataout[ncar*ncar*nslice*2]={0};

// Données sur le format de sortie
double FieldR[ncar][ncar][nslice]={0};
double FieldC[ncar][ncar][nslice]={0};


// Ouverture du fichier binaire à traiter
FILE* fichier = NULL;
fichier=fopen("templateTD.out.fld","rb");

// templateTD.out.fld
printf("opened \n");

// Lecture du fichier
if (fichier != NULL)
{
for(i=0;i<Ndatatot;i++)
{
// fscanf(fichier,"%lf", &data[i]);
fread(&data[i],sizeof(double),1,fichier);

}
printf("Data %e, %e, %e \n", data[0], data[1],data[2]);
fclose(fichier);
}


// Lecture des données du fichier et écriture en matrices
for(s=0;s<nslice;s++)
{
si=s;
for(i=0;i<NdataR;i++)
{
xi=floor(i/ncar);
yi=i-ncar*(floor(i/ncar));
// si=0;
FieldR[xi][yi][si]=data[i+s*ncar*ncar*2];
}
cout << "fieldR : " << FieldR[0][0][s] << endl;
// cout << "fieldR : " << FieldR[0][1][0] << endl;
// cout << "fieldR : " << FieldR[0][2][0] << endl;

for(j=NdataR;j<NdataR+NdataC;j++)
{
xi=floor((j-NdataR)/ncar);
yi=j-ncar*(floor((j)/ncar));
// si=0;
FieldC[xi][yi][si]=data[j+s*ncar*ncar*2];
}
// cout << "fieldC : " << FieldC[0][0][0] << endl;
// cout << "fieldC : " << data[NdataR] << endl;
}

// Ecriture de la matrice en une seule colonne
for(s=0;s<nslice;s++)
{
si=s;
for(i=0;i<NdataR;i++)
{
xi=floor(i/ncar);
yi=i-ncar*(floor(i/ncar));
// si=0;
dataout[i+s*ncar*ncar*2]=FieldR[xi][yi][si];
// cout << "datai " << dataout[i] << endl;

// cout << "fieldR : " << FieldR[xi][yi][si] << endl;

// cout << "dataout : " << dataout[0] << endl;
}


for(j=NdataR;j<NdataR+NdataC;j++)
{
xi=floor((j-NdataR)/ncar);
yi=j-ncar*(floor(j/ncar));
// si=0;
dataout[j+s*ncar*ncar*2]=FieldC[xi][yi][si];
}
}

// Ecriture de la colonne dans un fichier
cout << "Ecriture" << endl;

FILE* fichier2 = NULL;

fichier2=fopen("dataout.txt","w");
if (fichier2 != NULL)
{
for(i=0;i<Ndatatot;i++)
{
fprintf(fichier2,"%e \n", dataout[i]);
}
fprintf(fichier2,"\n");

fclose(fichier2);
}
printf("Data %e, %e, %e \n", dataout[0], dataout[1],dataout[2]);

return 0;
}

3 réponses

arth Messages postés 9374 Date d'inscription mardi 27 septembre 2005 Statut Contributeur Dernière intervention 16 décembre 2016 1 291
23 janv. 2008 à 20:01
Problème d'espace mémoire?
0
martiennette Messages postés 2 Date d'inscription mercredi 23 janvier 2008 Statut Membre Dernière intervention 24 janvier 2008
24 janv. 2008 à 09:38
Oui, tout simplement
La taille de mes matrices etait trop grosse.
je m'en suis finalement sortie en faisant un traitement bout par bout de mes données, ce qui evite de garder en mémoire de trop grosses matrices.

merci

marie
0
Mahmah Messages postés 496 Date d'inscription lundi 17 septembre 2007 Statut Membre Dernière intervention 22 juin 2010 125
24 janv. 2008 à 10:19
Bonjour,

En effet, j'avais fait un léger test hier soir et plouf !

Le problème n'est pas la taille mais l'endroit. En temps que variables locales d'une fonction, tes tableaux sont stockés dans la pile. C'est comme une pile d'assiette, on stocke en ajoutant au dessus chaque fois, elles sont toutes visibles (accessibles) mais on ne peut les retirer qu'à partir du dessus de la pile.

Si vous savez ce qu'est la pile vous pouvez sauter le paragraphe suivant.
Cette pile d'exécution sert au bon déroulement du programme pour:
- stocker les variables locales.
- stocker les paramètres lors d'appels de fonctions.
- stocker les paramètres de convention d'appel des fonctions. ( On veut appeler une fonction: on stocke la valeur de chaque paramètre dans la pile puis on stocke l'adresse de retour (c'est à dire là où il faudra reprendre quand la fonction fera son return) on stocke l'adresse de la base de la pile (je ne sais plus dans quel ordre avec l'adresse de retour) L'adresse de la base de la pile est simplement décalée pour que chaque fonction puisse utiliser cette adresse comme si la pile n'était que pour elle. Dans le cas des conventions d'appels C++ il y a encore un paramètre supplémentaire mais je ne sais plus lequel. (Mais celà jusitife tout simplement l'incompatibilité des appels et la nécessité du extern "C" pour rendre compatible le C++ avec le C lors d'exports de fonctions.



Pour résoudre le problème et travailler avec les tailles souhaitées pour les tableaux on peut:

Déclarer les tableaux dans l'environnement global (en dehors de toute fonction donc, et c'est ce que je ferais ici car le programme est court)
Ou
Allouer dynamiquement les tableaux.
   double *p = NULL;

   p = (double*) malloc( X * sizeof( double ) );   // Avec X le nombre de doubles voulus.

   if ( p!= NULL )
   {
      ...
      for ( unsigned int i = 0 ; i != X ; i++ )
         p[i] =        // notation identique à celle des tableaux
      ...
      free( p ); // Fin d'utilisation, libération de la mémoire allouée.
   }


Et voilou.

M.
0