J'ai une petite question (en fait 2) sur la programmation en C.
Je pense que je connais bien les techniques du C, mais je ne sais pas
bien programmer. Je vous donne un exemple :
Supposons que j'ai une structure avec plusieurs champs qui sont des
pointeurs (par exemple des chaînes de caractères char * et pas char []).
Ces char* représentents des informations que je récupère par un read sur
une socket par exemple. Je ne connais pas à l'avance la taille de ces
chaînes, donc je ne peux pas faire de char[]. Je pourrais évidemment
tronqué les chaines et donc les déclarer de type char[MAX_SIZE], ce que
je dois faire ni plus ni moins avec des char * pour ne pas lire
indéfiniment. Mais dans ce cas si je ne lis que 5 octets je perds
beaucoup de place (car MAX_SIZE >> 5). Donc pour en revenir au problème,
je fais des malloc sur chaque char*. Le problème est que quand je dois
libérer cette structure, je dois faire autant de free qu'il n'y a de
champs. Pire si une ou plusieurs fonctions remplissent au fur et à
mesure cette structure et que celles ci échouent, je dois libérer les
champs qui ont été préalablement alloué.
Donc techniquement pas de problème, par contre je trouve que le code
est vraiment lourd. Bien entendu, ce n'est pas tout a fait le problème
que j'ai, mais il est de ce style : revenir à un état cohérent quand une
fonction a échoué (si on ouvre une socket, et que l'instruction suivante
échoue, il faut fermer la socket ...)
Quand je regarde les codes source d'Apache, PostgreSQL, ... j'ai
l'impression qu'ils ne sont pas confronté à ce genre de problème, ou
alors qu'ils le gèrent différement. La technique que j'utilise (en ce
qui concerne l'allocation, mais je n'ai pas de solution dans le cas
général) est que mes structures ont une grande zone de mémoire (char *)
et que les char * suivant ne sont que des références à certaines parties
du permier char *. Ainsi si j'ai un problème, je ne libère que le
premier char *. Mais bon, je réalise que même si je connais
techniquement le C, je ne sais pas programmer. Donc si vous pouviez me
donner une ou deux conseils, ou me conseiller un livre. J'ai cherché,
mais tout ce que j'ai trouvé ne fait qu'expliquer la technique, et pas
la façon de programmer (réutilisable, maintenable). Je ne connais pas
les règles de programmation : par exemple est ce que quand une fonction
prend comme paramètre un char ** on s'attend a ce qu'elle alloue de la
mémoire ?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Bruno Desthuilliers
Frédéri MIAILLE wrote: (snip)
typedef struct ma_struct { Reset(){...un=NULL; deux=NULL;...} Clear(){if(un)Free(un); if(deux)free(deux); Reset();} Insert(void *_Dataun, void *_Datadeux...){mallocmachin, memcopytruc...} // ou encore faire une méthode pour chaque allocation, voire une fonction à nombre d'arguments variable... char * un; char * deux; char * trois; char * quatre; } ma_struct;
int main(void) { mystruct m; int res = m.nothing(); m.num = 1; return 0; }
[ dev]$ gcc -Wall -ansi -pedantic -o methods methods.c methods.c:4: field `nothing' declared as a function methods.c:4: warning: no semicolon at end of struct or union methods.c:4: parse error before '{' token methods.c:9: parse error before '}' token methods.c:9: warning: type defaults to `int' in declaration of `mystruct' methods.c:9: ISO C forbids data definition with no type or storage class methods.c: In function `main': methods.c:13: parse error before "m" methods.c:14: `m' undeclared (first use in this function) methods.c:14: (Each undeclared identifier is reported only once methods.c:14: for each function it appears in.) methods.c:14: warning: unused variable `res'
Tu ne confondrais pas avec C++, par hasard ?-)
Bruno
Frédéri MIAILLE wrote:
(snip)
typedef struct ma_struct
{
Reset(){...un=NULL; deux=NULL;...}
Clear(){if(un)Free(un); if(deux)free(deux); Reset();}
Insert(void *_Dataun, void *_Datadeux...){mallocmachin, memcopytruc...} //
ou encore faire une méthode pour chaque allocation, voire une fonction à
nombre d'arguments variable...
char * un;
char * deux;
char * trois;
char * quatre;
} ma_struct;
int main(void)
{
mystruct m;
int res = m.nothing();
m.num = 1;
return 0;
}
[laotseu@localhost dev]$ gcc -Wall -ansi -pedantic -o methods methods.c
methods.c:4: field `nothing' declared as a function
methods.c:4: warning: no semicolon at end of struct or union
methods.c:4: parse error before '{' token
methods.c:9: parse error before '}' token
methods.c:9: warning: type defaults to `int' in declaration of `mystruct'
methods.c:9: ISO C forbids data definition with no type or storage class
methods.c: In function `main':
methods.c:13: parse error before "m"
methods.c:14: `m' undeclared (first use in this function)
methods.c:14: (Each undeclared identifier is reported only once
methods.c:14: for each function it appears in.)
methods.c:14: warning: unused variable `res'
typedef struct ma_struct { Reset(){...un=NULL; deux=NULL;...} Clear(){if(un)Free(un); if(deux)free(deux); Reset();} Insert(void *_Dataun, void *_Datadeux...){mallocmachin, memcopytruc...} // ou encore faire une méthode pour chaque allocation, voire une fonction à nombre d'arguments variable... char * un; char * deux; char * trois; char * quatre; } ma_struct;
int main(void) { mystruct m; int res = m.nothing(); m.num = 1; return 0; }
[ dev]$ gcc -Wall -ansi -pedantic -o methods methods.c methods.c:4: field `nothing' declared as a function methods.c:4: warning: no semicolon at end of struct or union methods.c:4: parse error before '{' token methods.c:9: parse error before '}' token methods.c:9: warning: type defaults to `int' in declaration of `mystruct' methods.c:9: ISO C forbids data definition with no type or storage class methods.c: In function `main': methods.c:13: parse error before "m" methods.c:14: `m' undeclared (first use in this function) methods.c:14: (Each undeclared identifier is reported only once methods.c:14: for each function it appears in.) methods.c:14: warning: unused variable `res'
Tu ne confondrais pas avec C++, par hasard ?-)
Bruno
Frédéri MIAILLE
Un petit peu peut-être oui... :/ Je sors alors ? Tiens, tu m'indiques la porte que je la prenne discrètement...
int main(void) { mystruct m; int res = m.nothing(); m.num = 1; return 0; }
[ dev]$ gcc -Wall -ansi -pedantic -o methods methods.c methods.c:4: field `nothing' declared as a function methods.c:4: warning: no semicolon at end of struct or union methods.c:4: parse error before '{' token methods.c:9: parse error before '}' token methods.c:9: warning: type defaults to `int' in declaration of `mystruct' methods.c:9: ISO C forbids data definition with no type or storage class methods.c: In function `main': methods.c:13: parse error before "m" methods.c:14: `m' undeclared (first use in this function) methods.c:14: (Each undeclared identifier is reported only once methods.c:14: for each function it appears in.) methods.c:14: warning: unused variable `res'
Tu ne confondrais pas avec C++, par hasard ?-)
Pourtant, avec quelques modifications, ça marche :
/* methods.c */ typedef struct mystruct { int (*nothing)(void); int num; } mystruct;
int nothing(void) { return 0; }
int main(void) { mystruct m = {nothing, 0}; int res = m.nothing(); m.num = 1; return 0; }
$ gcc -W -Wall -ansi -pedantic -O2 methods.c -o methods methods.c: Dans la fonction « main »: methods.c:17: AVERTISSEMENT: variable inutilisée « res »
int main(void)
{
mystruct m;
int res = m.nothing();
m.num = 1;
return 0;
}
[laotseu@localhost dev]$ gcc -Wall -ansi -pedantic -o methods methods.c
methods.c:4: field `nothing' declared as a function
methods.c:4: warning: no semicolon at end of struct or union
methods.c:4: parse error before '{' token
methods.c:9: parse error before '}' token
methods.c:9: warning: type defaults to `int' in declaration of `mystruct'
methods.c:9: ISO C forbids data definition with no type or storage class
methods.c: In function `main':
methods.c:13: parse error before "m"
methods.c:14: `m' undeclared (first use in this function)
methods.c:14: (Each undeclared identifier is reported only once
methods.c:14: for each function it appears in.)
methods.c:14: warning: unused variable `res'
Tu ne confondrais pas avec C++, par hasard ?-)
Pourtant, avec quelques modifications, ça marche :
/* methods.c */
typedef struct mystruct
{
int (*nothing)(void);
int num;
} mystruct;
int nothing(void)
{
return 0;
}
int main(void)
{
mystruct m = {nothing, 0};
int res = m.nothing();
m.num = 1;
return 0;
}
$ gcc -W -Wall -ansi -pedantic -O2 methods.c -o methods
methods.c: Dans la fonction « main »:
methods.c:17: AVERTISSEMENT: variable inutilisée « res »
int main(void) { mystruct m; int res = m.nothing(); m.num = 1; return 0; }
[ dev]$ gcc -Wall -ansi -pedantic -o methods methods.c methods.c:4: field `nothing' declared as a function methods.c:4: warning: no semicolon at end of struct or union methods.c:4: parse error before '{' token methods.c:9: parse error before '}' token methods.c:9: warning: type defaults to `int' in declaration of `mystruct' methods.c:9: ISO C forbids data definition with no type or storage class methods.c: In function `main': methods.c:13: parse error before "m" methods.c:14: `m' undeclared (first use in this function) methods.c:14: (Each undeclared identifier is reported only once methods.c:14: for each function it appears in.) methods.c:14: warning: unused variable `res'
Tu ne confondrais pas avec C++, par hasard ?-)
Pourtant, avec quelques modifications, ça marche :
/* methods.c */ typedef struct mystruct { int (*nothing)(void); int num; } mystruct;
int nothing(void) { return 0; }
int main(void) { mystruct m = {nothing, 0}; int res = m.nothing(); m.num = 1; return 0; }
$ gcc -W -Wall -ansi -pedantic -O2 methods.c -o methods methods.c: Dans la fonction « main »: methods.c:17: AVERTISSEMENT: variable inutilisée « res »
-- Richard
Laurent Deniau
Richard Delorme wrote:
Je n'ai pas de titre à conseiller, mais peut-être un de ceux décrit ici te conviendrais : http://www.accu.org/bookreviews/public/reviews/0hr/writing_solid_code.htm
Il manque Unleashed C dans cette liste qui, bien que d'un niveau moyen, couvre pas mal de sujets.
a+, ld.
-- [ Laurent Deniau -- Scientific Computing & Data Analysis ] [ CERN -- European Center for Nuclear Research ] [ - http://cern.ch/Laurent.Deniau ] [ -- One becomes old when dreams become regrets -- ]
Richard Delorme wrote:
Je n'ai pas de titre à conseiller, mais peut-être un de ceux décrit ici te
conviendrais :
http://www.accu.org/bookreviews/public/reviews/0hr/writing_solid_code.htm
Il manque Unleashed C dans cette liste qui, bien que d'un niveau moyen, couvre
pas mal de sujets.
a+, ld.
--
[ Laurent Deniau -- Scientific Computing & Data Analysis ]
[ CERN -- European Center for Nuclear Research ]
[ Laurent.Deniau@cern.ch - http://cern.ch/Laurent.Deniau ]
[ -- One becomes old when dreams become regrets -- ]
Je n'ai pas de titre à conseiller, mais peut-être un de ceux décrit ici te conviendrais : http://www.accu.org/bookreviews/public/reviews/0hr/writing_solid_code.htm
Il manque Unleashed C dans cette liste qui, bien que d'un niveau moyen, couvre pas mal de sujets.
a+, ld.
-- [ Laurent Deniau -- Scientific Computing & Data Analysis ] [ CERN -- European Center for Nuclear Research ] [ - http://cern.ch/Laurent.Deniau ] [ -- One becomes old when dreams become regrets -- ]