IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Tableau multidimensionnel et allocation


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2006
    Messages : 21
    Points : 23
    Points
    23
    Par défaut Tableau multidimensionnel et allocation
    Salut,
    j'ai écrit une fonction pour faire la chose suivante: je voudrais que ma fonction m'alloue de la mémoire pour un tableau de pointeurs vers des pointeurs de chaînes de caractère de taille n. Voici le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    char*** _alloc(int n, int m, int r)
    {
    	char*** p;
    	int i;
    	int j;
    	/* Adresse du tableau de pointeurs vers des pointeurs de char* */
    	p = malloc(sizeof*p); 
    	if (p == NULL) 
    	{
    		fprintf(stderr,"Allocation impossible\n");
    		exit(-1);
    	}
    	*p = malloc(n*sizeof(char**));
    	if ( *p == NULL)
    	{
    		fprintf(stderr,"Allocation impossible\n");
    		exit(-1);
    	}
    	else
    	{
    		for(i=0; i < n; i++)
    		{
    			*p[i] = calloc(m,sizeof(char*));
    			if (*p[i] == NULL)
    			{
    				printf("Allocation impossible\n");
    				exit(-1);
    			}
    		}
    	}
    	**p = malloc(HASH_SIZE*sizeof(char));
    	return p;
    }
    Dans mon application, je lis un fichier qui est composée de 23 lignes et alloue mon tableau avec le triplet (1,23,taille du hash).
    Voici le code de ma fonction main():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    int main(void)
    {
    	FILE* datafile;
    	FILE* fd;
    	const char* path;
    	int (*between_hashes)(const char*,const char*,const char*);
    	path = "/home/jro/doc/diploma/projet/src/data.txt";
    	char line[BUFSIZ];
    	char data_hash[HASH_SIZE];
    	char id[HASH_SIZE];
    	char*** set_data;
    	int nline;
    	between_hashes = between_hashes_sha1;
    	/*Initialisation des fonctions de manipulation du hash.*/
     
    	if (NULL == (datafile = fopen(path,"r")))
    	{
    		fprintf(stderr,"Impossible d'ouvrir fichier %s\n",path);
    		exit(-1);
    	}
    	nline = count_line(fd,path);
    	DEBUGP("_alloc()");
    	set_data = _alloc(1,nline,HASH_SIZE);
    	int pos = 0;
    	while (fgets(line,BUFSIZ,datafile))
    	{
    		calculate_hash(line, data_hash, NULL);
    		strcpy(set_data[0][pos],data_hash);
    		pos++;  
    	//	printf("%s(%s)\n",data_hash,line);	
    	}
    	int i;
    	i = between_hashes(set_data[0][0], set_data[0][1], set_data[0][2]);
    	(i != 1) ? pr("not between") : pr("between");
    	i = between_hashes(set_data[0][2], set_data[0][1], set_data[0][0]);
    	(i != 1) ? pr("not between") : pr("between");
    	if (!feof(datafile))
    	{
    		fprintf(stderr,"Erreur de lecture du fichier!!\n");
    		exit(-1);
    	}
    	fclose(datafile);
    	return 0;
    }
    J'ai un signal SIGSEGV à la ligne ou se trouve strcpy(). Je pense que dans mon allocation, il y une erreur. J'ai, en effet, fait un test et j'arrive à copier dans set_data[0][0] et non pas dans set_data[0][1]. Ai-je probablement oublié d'allouer de la mémoire quelque part dans ma fonction _alloc()?
    Johnny.

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par jro-daemon
    j'ai écrit une fonction pour faire la chose suivante: je voudrais que ma fonction m'alloue de la mémoire pour un tableau de pointeurs vers des pointeurs de chaînes de caractère de taille n. Voici le code:
    C'est pas extrêmement clair tout ça ...

    Si le but est de créer un tableau dynamique à 3 dimensions, il faut 2 boucles imbriquées...

    Le principe est rappelé ici (2 dimensions)

    http://emmanuel-delahaye.developpez.....htm#tabdyn_2d

    en tout cas, la fonction _alloc() ne fait pas du tout ça...

    n, m et r sont les 3 dimensions ? Si c'est le cas,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	char*** p;
            <...>
    	p = malloc(sizeof*p);
    ca commence très mal...

    Ca devrait être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	char*** ppp = malloc(sizeof * ppp * n);
    ensuite une boucle 0..n avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	ppp[i] = malloc (sizeof * ppp[i] * m);
    et pour chaque i : une boucle 0..m avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	ppp[i][j] = malloc (sizeof * ppp[i][j] * r);
    • cette fonction est mal nommée. Les _ en début d'identificateurs sont réservés à l'implémentation.
    • cette fonction ne devrait pas être polluée par des informations exterieurs du type 'HASH_SIZE'... Si c'est nécessaire, ajouter un paramètre...
    • donne un exemple d'utilisation beaucoup plus simple et surtout complet et compilable (C standard).

    Réécrit la fonction et le main() sur ces bases, après on verra.
    Pas de Wi-Fi à la maison : CPL

  3. #3
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2006
    Messages : 21
    Points : 23
    Points
    23
    Par défaut
    Salut Emmanuel,
    Voici mon nouveau code, je pense que ce que j'ai écrit est dû au fait de l'heure tardive. De plus, ce qui me gênait était de faire un tableau de pointeurs de pointeurs de char* mais le principe reste exactement le même que pour un tableau à deux dimensions. En tout cas voici une écriture beaucoup plus propre de ma fonction que j'ai nommé cette fois-ci alloc3d:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    char*** alloc3d(int n, int m, int r)
    {
    	char*** ppp;
    	int i;
    	int j;
    	/* Adresse du tableau de pointeurs vers des pointeurs de char* */
    	ppp = malloc(sizeof*ppp*n); 
    	if (ppp == NULL) 
    	{
    		fprintf(stderr,"Allocation impossible\n");
    		exit(-1);
    	}
    	for(i = 0;i < n; i++)
    	{
    		ppp[i] = malloc(m*sizeof*ppp[i]);
    		for (j=0; j < m; j++)
    		{
    			ppp[i][j] = malloc(r*sizeof*ppp[i][j]);
    		}
    	}
    	return ppp;
    }
    Et voici mon application de cette fonction. Il s'agit tout simplement de ranger de ranger un sha1 digest que je calcule pour chaque donnée que je lis depuis un fichier texte. Et puis, je fais des manipulations avec trois d'entre elles pour voir l'ordre dans lesquels elles sont rangées. Voici le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    int main(void)
    {
    // 	const char* ip = "192.168.123.124";
    // 	unsigned int port;
    // 	unsigned char* nodeid;
    	FILE* datafile;
    	FILE* fd;
    	const char* path;
    	int (*between_hashes)(const char*,const char*,const char*);
    	path = "/home/jro/doc/diploma/projet/src/data.txt";
    	char line[BUFSIZ];
    	char data_hash[HASH_SIZE];
    	char id[HASH_SIZE];
    	char*** set_data;
    	int nline;
    	between_hashes = between_hashes_sha1;
    	/*Initialisation des fonctions de manipulation du hash.*/
     
    	if (NULL == (datafile = fopen(path,"r")))
    	{
    		fprintf(stderr,"Impossible d'ouvrir fichier %s\n",path);
    		exit(-1);
    	}
    	nline = count_line(fd,path);
    	set_data = alloc3d(1,nline,HASH_SIZE);
    	int pos = 0;
    	while (fgets(line,BUFSIZ,datafile))
    	{
    		calculate_hash(line, data_hash, NULL);
    		strcpy(set_data[0][pos],data_hash);
    		pos++;  
    	//	printf("%s(%s)\n",data_hash,line);	
    	}
    	int i;
    	i = between_hashes(set_data[0][0], set_data[0][1], set_data[0][2]);
    	(i != 1) ? pr("not between") : pr("between");
    	i = between_hashes(set_data[0][2], set_data[0][1], set_data[0][0]);
    	(i != 1) ? pr("not between") : pr("between");
    	if (!feof(datafile))
    	{
    		fprintf(stderr,"Erreur de lecture du fichier!!\n");
    		exit(-1);
    	}
    	//cal_nodeid(ip,port,nodeid)
    	fclose(datafile);
    	return 0;
    Merci de m'avoir éclairer sur cette histoire d'allocation.
    Cordialement,
    Johnny

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par jro-daemon
    Voici mon nouveau code,
    OK. Mais attention, tous les malloc() peuvent échouer...Il manque donc des tests...

    Quand au main(), beaucoup trop complexe pour que je m'y plonge.
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    21
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2006
    Messages : 21
    Points : 23
    Points
    23
    Par défaut
    Salut,
    oui c'est ce que je me suis dit en regardant mon code après coup donc j'ai mis les tests en place. . La mémoire c'est vraiment délicat donc vaut mieux être prudent. Mais, il m'est déjà arrivé lorsque le nombre d'allocation dynamique à effectuer deviennent importantes. Que recommendes-tu si une ou plusieurs allocations deviennent impossibles? Y'a-t-il un moyen de voir quelles sont les emplacements mémoire réservées aus allocations dynamiques qui sont inutilisées parce que non libérées? Si quelqu'un pouvait m'en dire plus...
    Pas de problème pour le main(). je n'ai pas posté un fichier complet et puis j'ai réussi à effectuer les tests que je voulais à l'heure ou j'écris.

  6. #6
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Points : 17 916
    Points
    17 916
    Billets dans le blog
    2
    Par défaut
    comme on l'a dit dans un autre post :

    • soit tu prends les grands moyens, et tu fais un code sûr réellement, dans ce cas-là pour ton genre d'imbrications il n'y a que 2 solutions :
      • - ou tu sors par des breaks de chaque boucle en libérant ce qui peut l'être au passage
      • - ou tu continues, en testant à chaque utilisation que tu n'es pas sur un emplacement non alloué
    • soit tu prends les plus petits, et tu sors du programme après avoir affiché un message explicatif
    ...

    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 376
    Points : 41 545
    Points
    41 545
    Par défaut
    C'est clair que ça fait beaucoup d'allocations.
    Pour un vrai tableau multidimensionnel, je conseillerais plutôt de se limiter à une allocation par dimension :
    http://www.developpez.net/forums/sho...70&postcount=7
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 06/07/2011, 15h35
  2. Réponses: 2
    Dernier message: 27/11/2005, 23h36
  3. Nombre de dimensions d'un tableau multidimensionnel
    Par Bruno75 dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 08/07/2005, 10h03
  4. type de donnée tableau multidimensionnel
    Par opheliegomes dans le forum Débuter
    Réponses: 2
    Dernier message: 03/02/2005, 12h29
  5. [langage] tableau multidimensionnel
    Par totox17 dans le forum Langage
    Réponses: 3
    Dernier message: 03/12/2002, 15h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo