Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Pb malloc realloc avec des tableaux de structures

13 réponses
Avatar
David Roman CESR
typedef struct {
char Key[13];
int Nb;
uint *List;
} List

ListTri **Ti_Se;

memset(Ti_Se,NULL,nEltsMax*sizeof(ListTri));


if (Ti_Se[0]==NULL) {

Ti_Se[0]=(ListTri *) malloc(sizeof(ListTri));
sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
Ti_Se[0]->Nb=101;

Ti_Se[0]->List=(uint *) malloc(sizeof(uint));
Ti_Se[0]->List[0]=20;

Ti_Se[0]->List=(uint *) realloc(Ti_Se[0]->List,2*sizeof(uint));
Ti_Se[0]->List[1]=30;

printf("AAA %i %s %i
%i\n",Ti_Se[0]->Nb,Ti_Se[0]->Key,Ti_Se[0]->List[0],Ti_Se[0]->List[1]);
}



Mon code est visiblement faux (pas pour moi sinon je poserai pas la
question)
Lorsque je j'etends la zone memoire du champs List de la structure,
j'ecrase
la valeur initiale du champ.

Que faut il ecrit pour que ce soit bon ???

10 réponses

1 2
Avatar
Bertrand Mollinier Toublet
Alors, reprenons:

David Roman CESR wrote:
typedef struct {
char Key[13];
int Nb;
uint *List;
} List

As-tu reellement besoin d'un typedef, ou bien n'est ce que pour

t'economiser de la saisie (dans le meme esprit que l'immonde, et a
eviter, uint) ?

#include <stdlib.h>
#include <stdio.h>

struct list_s {
char key[13];
int nb;
unsigned int *list;
};

ListTri **Ti_Se;

void foo(void)

{
struct list_s **ti_se;
size_t elem_cnt = /*whatever*/;

memset(Ti_Se,NULL,nEltsMax*sizeof(ListTri));


Non, je ne pense pas, non:

a) tu modifies de la memoire qui ne t'appartient pas (ou' as-tu
initialise Ti_Se ?)
b) le second argument de memset (pour lequel, au moins dans le code que
tu nous montres, tu n'as pas de prototype en vue...) est bien un int,
pas un pointeur.
c) utiliser 0 comme int pour initialiser la memoire a zero n'est une
methode sure que pour initialiser des char.

A la place tu veux allouer de la memoire pour ti_se:

ti_se = malloc(elem_cnt * sizeof *ti_se);

Tu remarques l'absence de cast (inutile et en fait dangereux) et le
sizeof sur la variable et non le type (utile quand le type de ta
variable change).

if (NULL == ti_se)
{
/* l'allocation a foire, tu dois gerer l'erreur... */
}
else
{

Tu voulais initialiser tous les pointeurs de ton tableau a NULL ? Soit:

size_t i;

for (i = 0; i < elem_cnt; i++) ti_se[i] = NULL;
}


if (Ti_Se[0]==NULL) {

Ti_Se[0]=(ListTri *) malloc(sizeof(ListTri));
La, c'est pareil. Pas besoin de cast pour ton malloc:

ti_se[0] = malloc(sizeof *ti_se[0]);
if (NULL == ti_se[0])
{
/* gerer l'allocation manquee de memoire */
}
sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
Tu m'expliques ? Tu reserves treize caracteres pour le champ key et tu

essayes de lui en faire bouffer 29 ?!?
sprintf(ti_se[0]->key, "%6.6i", 12345);
Ti_Se[0]->Nb1;


Ti_Se[0]->List=(uint *) malloc(sizeof(uint));
idem:

ti_se[0]->list = malloc(sizeof *(ti_se[0]->list));
if (NULL == ti_se[0]->list)
{
/* gerer l'allocation manquee de memoire */
}
Ti_Se[0]->List[0] ;

Ti_Se[0]->List=(uint *) realloc(Ti_Se[0]->List,2*sizeof(uint));
Pour le realloc, c'est encore plus subtil que pour le malloc. Que se

passe t'il si realloc foire ? Il te retourne NULL, mais ne desalloue pas
l'espace precedement alloue. Donc si tu attribue directement la valeur
de retour de realloc au pointeur vers l'espace que tu realloue, en cas
d'echec, ce pointeur est perdu et tu as une fuite de memoire. La facon
"correcte" de faire:
{
void *tmp;
tmp = realloc(ti_se[0]->list, 2 * sizeof *(ti_se[0]->list));
if (NULL == tmp)
{
/* gerer la reallocation manquee de memoire */
}
else
{
ti_se[0]->list = tmp;
}
}
Ti_Se[0]->List[1]0;

printf("AAA %i %s %i
%in",Ti_Se[0]->Nb,Ti_Se[0]->Key,Ti_Se[0]->List[0],Ti_Se[0]->List[1]);
}



--
Bertrand Mollinier Toublet
Blog: http://www.bmt.dnsalias.org/blog

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', David Roman CESR wrote:

typedef struct {
char Key[13];
int Nb;
uint *List;
} List


Manque un ';'

ListTri **Ti_Se;


'ListTri' non défini.

memset(Ti_Se,NULL,nEltsMax*sizeof(ListTri));


'Ti_Se' n'a jamais été initialisé. C'est le UB. Si c'est une variable locale
(recommandé en autre pour la raison qui suit), tu pourrais avoir un warning
genre 'utilisation d'une variable non initialisée' si ton compilateur est
bien reglé.

Pas la peine de regarder le reste. Il faut déjà corriger ça.

if (Ti_Se[0]==NULL) {

Ti_Se[0]=(ListTri *) malloc(sizeof(ListTri));
sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
Ti_Se[0]->Nb1;

Ti_Se[0]->List=(uint *) malloc(sizeof(uint));
Ti_Se[0]->List[0] ;

Ti_Se[0]->List=(uint *) realloc(Ti_Se[0]->List,2*sizeof(uint));
Ti_Se[0]->List[1]0;

printf("AAA %i %s %i
%in",Ti_Se[0]->Nb,Ti_Se[0]->Key,Ti_Se[0]->List[0],Ti_Se[0]->List[1]);
}

Mon code est visiblement faux (pas pour moi sinon je poserai pas la
question)
Lorsque je j'etends la zone memoire du champs List de la structure,
j'ecrase
la valeur initiale du champ.

Que faut il ecrit pour que ce soit bon ???


Déjà, enlever tous ces cast inutiles qui ne font que brouiller le message.
Ensuite retravailler un peu la présentation, qu'on y voit clair (je
recommande GNUIndent). Apprendre à couper les lignes longues proprement, et
pas à la barbare, mettre des espaces ...

Définir ce qui ne l'est pas, initialiser les pointeurs qui ne le sont pas...

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Bertrand Mollinier Toublet
wrote:

As-tu reellement besoin d'un typedef, ou bien n'est ce que pour
t'economiser de la saisie (dans le meme esprit que l'immonde, et a
eviter, uint) ?


Je ne trouve pas que 'uchar', 'uint' et 'ulong' soient immondes. Ils sont
clairs et facilitent emploi, codage et relecture. Bien sûr, il faut s'en
tenir à des définitions évidentes.

Extrait de ma bibliothèque perso:

typedef unsigned char uchar;
typedef signed char schar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Bertrand Mollinier Toublet
Emmanuel Delahaye wrote:
In 'fr.comp.lang.c', Bertrand Mollinier Toublet
wrote:

As-tu reellement besoin d'un typedef, ou bien n'est ce que pour
t'economiser de la saisie (dans le meme esprit que l'immonde, et a
eviter, uint) ?


Je ne trouve pas que 'uchar', 'uint' et 'ulong' soient immondes. Ils sont
clairs et facilitent emploi, codage et relecture. Bien sûr, il faut s'en
tenir à des définitions évidentes.

Extrait de ma bibliothèque perso:

typedef unsigned char uchar;
typedef signed char schar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;

Djihad !!


Ces considerations relevent de la guerre sainte. Restons-en la...
--
Bertrand Mollinier Toublet
[A] Top-posting.
[Q] What's the most annoying thing on Usenet ?


Avatar
David Roman CESR
Bertrand Mollinier Toublet wrote:


sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
Tu m'expliques ? Tu reserves treize caracteres pour le champ key et tu

essayes de lui en faire bouffer 29 ?!?
sprintf(ti_se[0]->key, "%6.6i", 12345);



Je suis un bleu en C, mais avec tous le respect que je dois a un maitre du
C
je voudrais te faire remaquer que
sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
a pour resultat la chaine suivante '123456123456' soit 12 caracteres + le
caractere de fin
ce qui fait bien 13 caracteres au total. SI SI essayes le tu verras par toi
meme.


Avatar
David Roman CESR
Emmanuel Delahaye wrote:

In 'fr.comp.lang.c', David Roman CESR wrote:

typedef struct {
char Key[13];
int Nb;
uint *List;
} List


Manque un ';'

ListTri **Ti_Se;


'ListTri' non défini.

memset(Ti_Se,NULL,nEltsMax*sizeof(ListTri));


'Ti_Se' n'a jamais été initialisé. C'est le UB. Si c'est une variable locale
(recommandé en autre pour la raison qui suit), tu pourrais avoir un warning
genre 'utilisation d'une variable non initialisée' si ton compilateur est
bien reglé.

Pas la peine de regarder le reste. Il faut déjà corriger ça.

if (Ti_Se[0]==NULL) {

Ti_Se[0]=(ListTri *) malloc(sizeof(ListTri));
sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
Ti_Se[0]->Nb1;

Ti_Se[0]->List=(uint *) malloc(sizeof(uint));
Ti_Se[0]->List[0] ;

Ti_Se[0]->List=(uint *) realloc(Ti_Se[0]->List,2*sizeof(uint));
Ti_Se[0]->List[1]0;

printf("AAA %i %s %i
%in",Ti_Se[0]->Nb,Ti_Se[0]->Key,Ti_Se[0]->List[0],Ti_Se[0]->List[1]);
}

Mon code est visiblement faux (pas pour moi sinon je poserai pas la
question)
Lorsque je j'etends la zone memoire du champs List de la structure,
j'ecrase
la valeur initiale du champ.

Que faut il ecrit pour que ce soit bon ???


Déjà, enlever tous ces cast inutiles qui ne font que brouiller le message.
Ensuite retravailler un peu la présentation, qu'on y voit clair (je
recommande GNUIndent). Apprendre à couper les lignes longues proprement, et
pas à la barbare, mettre des espaces ...

Définir ce qui ne l'est pas, initialiser les pointeurs qui ne le sont pas...

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
<blank line>
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


Bon j'ai repris mon code, j'espere avoir ete un peu meilleur ...?

#include <stdio.h>
#include <malloc.h>
#include <errno.h>
#include <sys/types.h>

typedef unsigned short int usint;

typedef struct {
char Key[13];
int Nb;
uint *List;
} ListTri;

int main (void)
{

int i,j;
char Key[13];

ListTri **Ti_Se;


//Allocation de 10 pointeurs vers des structures ListTri
Ti_Se=malloc(10*sizeof(ListTri *));
if (Ti_Se==NULL) {
printf("Erreur d'allocation mémoire !!!n");
exit(1);
}

//Initialise les pointeurs a 0 sizeof(NULL)=sizeof(ListTri *)=4
//J'initialise les pointeurs et non pas les structures (remarque pour
//Bertrand)
memset(Ti_Se,NULL,10*sizeof(ListTri *));

//Allocation pour un element du tableau vers un structure ListTri
Ti_Se[1]=malloc(sizeof(ListTri));
if (Ti_Se[1] == NULL) {
printf("Erreur d'allocation mémoire !!!n");
exit(1);
}

//Renseignement de la structure
sprintf(&Ti_Se[1]->Key[0],"%6.6i%6.6i",1234546,1234546);
Ti_Se[1]->Nb=1;
Ti_Se[1]->List=malloc(sizeof(uint));
if (Ti_Se[1]->List == NULL) {
printf("Erreur d'allocation mémoire !!!n");
exit(1);
}
Ti_Se[1]->List[0] ;


printf("Ti_Se[1]->Key =%sn",Ti_Se[1]->Key);
printf("Ti_Se[1]->Nb =%in",Ti_Se[1]->Nb);
printf("Ti_Se[1]->List[0]=%in",Ti_Se[1]->List[0]);
printf("n");

//Ajoute 2 elements dans le champ list
Ti_Se[1]->List=realloc(Ti_Se[1]->List,3*sizeof(uint));
if (Ti_Se[1]->List == NULL) {
printf("Erreur d'allocation mémoire !!!n");
exit(1);
}

Ti_Se[1]->Nb=3;
Ti_Se[1]->List[1]0;
Ti_Se[1]->List[2]@;

printf("Ti_Se[1]->Key =%sn",Ti_Se[1]->Key);
printf("Ti_Se[1]->Nb =%in",Ti_Se[1]->Nb);
printf("Ti_Se[1]->List[0]=%in",Ti_Se[1]->List[0]);
printf("Ti_Se[1]->List[1]=%in",Ti_Se[1]->List[1]);
printf("Ti_Se[1]->List[2]=%in",Ti_Se[1]->List[2]);
printf("n");

}


Est ce que la je suis bon pour obtenir mon diplome de programmeur C ????
Merci de ppour cos remarque.


Avatar
Yves ROMAN

typedef struct {
char Key[13];
int Nb;
uint *List;
} List

ListTri **Ti_Se;


Quelle est la definition de ListTri ?


memset(Ti_Se,NULL,nEltsMax*sizeof(ListTri));


Comment est alloué Ti_Se ?
Ti_Se pointe vers un tableau de ListTri *, mais tu RaZ un espace pour nEltsMax
elements de type ListTri

Ti_Se = malloc(nEltsMax*sizeof(*Ti_Se)) ;
if (Ti_Se != NULL )
for ( i = 0 ; i < nEltsMax ; i++ ) Ti_Se[i] = NULL ;
(au cas ou NULL ne serait pas represente par 0 en memoire)


if (Ti_Se[0]==NULL) {

Ti_Se[0]=(ListTri *) malloc(sizeof(ListTri));
sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);


Surement une coquille, mais ici ca deborde de 2 caracteres (le 4 en trop)

Ti_Se[0]->Nb1;

Ti_Se[0]->List=(uint *) malloc(sizeof(uint));
Ti_Se[0]->List[0] ;

Ti_Se[0]->List=(uint *) realloc(Ti_Se[0]->List,2*sizeof(uint));
Ti_Se[0]->List[1]0;

printf("AAA %i %s %i
%in",Ti_Se[0]->Nb,Ti_Se[0]->Key,Ti_Se[0]->List[0],Ti_Se[0]->List[1]);
}

Ca devrait passer avec les corrections d'allocation initiales


Avatar
Yves ROMAN

[...]


typedef struct {
char Key[13];
int Nb;
uint *List;
} ListTri;

[...]


//Renseignement de la structure
sprintf(&Ti_Se[1]->Key[0],"%6.6i%6.6i",1234546,1234546);


Heureusement qu'il y a du padding dans la structure
Essaye aussi avec
sprintf(&Ti_Se[1]->Key[0],"%6.6i%6.6i",123453456,123453456);

printf("n");

[...]

}



Il manque un return EXIT_SUCCES ; a la fin

Avatar
manu l.
"David Roman CESR" a écrit dans le message de
news:


Bon j'ai repris mon code, j'espere avoir ete un peu meilleur ...?

#include <stdio.h>
#include <malloc.h>
#include <errno.h>


Pourquoi ? Ca n'est utile nulle part.

<errno.h> définit EDOM (pour les erreurs de domaine), ERANGE (pour les
erreurs d'intervalle), pour le traitement des conditions d'erreur des
fonctions mathématiques, rangées dans errno (également définie ici) selon
besoins. Toute autre utilisation est éminemment non portable. (Même si il
est toujours utile et intéressant de connaître le jeu de code d'erreurs de
son système).

#include <sys/types.h>


Si l'on veut, mais ce n'est pas standard.

(...)

Est ce que la je suis bon pour obtenir mon diplome de programmeur C ????
Merci de ppour cos remarque.



Ben, pour le C ISO, faudra bûcher encore.

Amicalement.

--
manu l.

Avatar
halfwolf
David Roman CESR wrote in message news:...
Je suis un bleu en C, mais avec tous le respect que je dois a un maitre du
C
je voudrais te faire remaquer que
sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
a pour resultat la chaine suivante '123456123456' soit 12 caracteres + le
caractere de fin
ce qui fait bien 13 caracteres au total. SI SI essayes le tu verras par toi
meme.


sprintf(Ti_Se[0]->Key,"%6.6i%6.6i",1234546,1234546);
a pour resultat la chaine suivante '12345461234546' soit 14 caracteres
+ le caractere de fin ce qui fait 15 caracteres au total.
SI SI essayes le tu verras par toi meme.

Je vais même plus loin, je te propose un programme de test :

# include <stdio.h>

int main(void)
{
int nbCharWritten;

nbCharWritten = printf("%6.6i%6.6i",1234546,1234546);
printf("n%d char writtenn", nbCharWritten);

return 0;
}

ce qui donne :

12345461234546
14 char written

En effet, %6.6i te garantit d'afficher AU MOINS 6 caractères pour ta
valeur. 1234546 en fait 7.

Certes ça ne fait pas 29, mais en attendant tu as quand même faux.
Manipuler l'ironie fasse à quelqu'un qui te répond pour t'aider alors
que, tu le dis toi-même, tu es un bleu en C, je trouve ça plutôt
irrespectueux.

HalfWolf, qui n'est pas content

1 2