Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Une C extension qui ..... marche pas

19 views
Skip to first unread message

mou...@igbmc.u-strasbg.fr

unread,
Oct 19, 2012, 8:21:27 AM10/19/12
to

Bonjour tout le monde !!

Avant de partir en we, ce serait super-sympa de m'aider à debugger ce code ? C'est une extension C pour Tcl qui plante :
- soit pour un probleme d'allocation
- soir pour la desallocation
J'ai mis les points qui plante/que je ne comprends pas en commentaire !!

Un grand merci à vous !
Luc

static int Ccode_Pairwise (ClientData cdata,
Tcl_Interp *interp,
int objc,
Tcl_Obj * CONST objv[]) {
char *seq0, **tseq=NULL;
int nseq, i, j, alen;
int l,l1,l2;
Tcl_Obj **Lseq, *Tpci, *pair;
double **tres, *tlg, dist;

if (Tcl_ListObjGetElements(interp,objv[1],&nseq,&Lseq) != TCL_OK) {
return TCL_ERROR;
}

/* allocation */
/*COMPILATION ! Le compilo me dit :
warning: pointer targets in assignment differ in signedness
*/
seq0 = Tcl_GetByteArrayFromObj(Lseq[1],&alen);
tseq = (char **)ckalloc((nseq+1)*sizeof(char *));
for (i=0; i<nseq; i++) {
tseq[i] = (char *)ckalloc((alen+1)*sizeof(char));
}
tseq[nseq] = NULL;

tres =(double **)ckalloc((nseq+1)*sizeof(double *));
for (i=0; i<nseq; i++) {
tres[i] = (double *)ckalloc((nseq+1)*sizeof(double));
}
tres[nseq] = NULL;
tlg =(double *)ckalloc((nseq+1)*sizeof(double));

for (i=0;i<nseq;i++) {
/*COMPIL : meme erreur
tseq[i] = Tcl_GetByteArrayFromObj(Lseq[i],&alen);
l=0;
for (j=0;j<alen;j++) {
if (tseq[i][j] != '.') l++;
}
tlg[i]=(double)l;
}

for (i=0; i<nseq-1; i++) {
for (j=i+1; j<nseq; j++) {
dist = SeqMatch(tseq[i],tseq[j],alen);
tres[i][j] = tres[j][i] = dist;
}
}

/* ici je construis une liste de liste qui sera le resultat final */
Tpci = Tcl_NewListObj(0,NULL);
for (i=0; i<nseq; i++) {
l1=tlg[i];
tres[i][i]=(double)l1;
for (j=0; j<nseq; j++) {
l2=tlg[j];
pair = Tcl_NewListObj(0,NULL);

if (l1 == 0 || l2 == 0) {
dist = 0.0;
} else {
dist = tres[i][j]/(double)(l1<=l2?l1:l2);
}
Tcl_ListObjAppendElement(interp,pair,Tcl_NewDoubleObj(dist));
/*PLANTAGE refuse d'allouer */
Tcl_ListObjAppendElement(interp,pair,Tcl_NewIntObj(l1));
Tcl_ListObjAppendElement(interp,pair,Tcl_NewIntObj(l2));
Tcl_ListObjAppendElement(interp,pair,Tcl_NewDoubleObj((l1<l2?(double)(l1)/l2:(double)(l2)/l1)));

Tcl_ListObjAppendElement(interp,Tpci,pair);
}
}

Tcl_SetObjResult(interp,Tpci);

/* desallocation */
ckfree((char *)tlg);
for (i=0; i<nseq; i++) {
/* PLANTAGE */
ckfree((char *)tseq);
ckfree((char *)tres[i]);
}
ckfree((char *)tseq);
ckfree((char *)tres);

return TCL_OK;
}

Frederic Bonnet

unread,
Oct 19, 2012, 9:30:17 AM10/19/12
to
Le 19/10/2012 14:21, luc.mo...@igbmc.fr a écrit :
>
> Bonjour tout le monde !!
>
> Avant de partir en we, ce serait super-sympa de m'aider à debugger ce code ? C'est une extension C pour Tcl qui plante :
> - soit pour un probleme d'allocation
> - soir pour la desallocation
> J'ai mis les points qui plante/que je ne comprends pas en commentaire !!
>
> Un grand merci à vous !
> Luc
>
> static int Ccode_Pairwise (ClientData cdata,
> Tcl_Interp *interp,
> int objc,
> Tcl_Obj * CONST objv[]) {
> char *seq0, **tseq=NULL;
> int nseq, i, j, alen;
> int l,l1,l2;
> Tcl_Obj **Lseq, *Tpci, *pair;
> double **tres, *tlg, dist;
>
> if (Tcl_ListObjGetElements(interp,objv[1],&nseq,&Lseq) != TCL_OK) {
> return TCL_ERROR;
> }
>
> /* allocation */
> /*COMPILATION ! Le compilo me dit :
> warning: pointer targets in assignment differ in signedness
> */
> seq0 = Tcl_GetByteArrayFromObj(Lseq[1],&alen);

Pas grave : Tcl_GBFO retourne un unsigned char * que tu assignes à une
variable char *. Un petit cast ou un unsigned sur la définition fera
l'affaire.


> tseq = (char **)ckalloc((nseq+1)*sizeof(char *));
> for (i=0; i<nseq; i++) {
> tseq[i] = (char *)ckalloc((alen+1)*sizeof(char));
> }
> tseq[nseq] = NULL;
>
> tres =(double **)ckalloc((nseq+1)*sizeof(double *));
> for (i=0; i<nseq; i++) {
> tres[i] = (double *)ckalloc((nseq+1)*sizeof(double));
> }
> tres[nseq] = NULL;
> tlg =(double *)ckalloc((nseq+1)*sizeof(double));
>
> for (i=0;i<nseq;i++) {
> /*COMPIL : meme erreur
> tseq[i] = Tcl_GetByteArrayFromObj(Lseq[i],&alen);

Itou.
C'est parce que tu appelles ckfree sur tseq plusieurs fois dans ta
boucle. Supprime cette ligne vu que tu répètes l'opération en sortie :


> ckfree((char *)tres[i]);
> }
> ckfree((char *)tseq);

... ici.

> ckfree((char *)tres);
>
> return TCL_OK;
> }
>


Le reste me paraît correct. Je ne vois pas d'où vient le plantage sur
Tcl_ListObjAppendElement.

A++, Fred

mou...@igbmc.u-strasbg.fr

unread,
Oct 19, 2012, 10:18:28 AM10/19/12
to
Merci Fred !

Je vais abuser de ta gentillesse pour ma culture et mon edification :
tres =(double **)ckalloc((nseq+1)*sizeof(double *));
for (i=0; i<nseq; i++) {
tres[i] = (double *)ckalloc((nseq+1)*sizeof(double));
}
tres[nseq] = NULL;

J'alloue un pointeur de pointeur. J'en alloue nseq+1

Quand on desalloue,
for (i=0; i<nseq; i++) {
ckfree((char *)tres[i]);
}
ckfree((char *)tres);

J'en desalloue nseq, et le dernier ckfree desalloue le nseq+1 ieme.

Ou bien un seul ckfree() va desallouer tout le monde ?

Tant que j'y suis, ne faut-il pas desallouer le tableau de Tcl_Obj **Lseq ?

Merci de m'éclairer !!
Luc

Frederic Bonnet

unread,
Oct 19, 2012, 10:38:44 AM10/19/12
to
Le 19/10/2012 16:18, luc.mo...@igbmc.fr a écrit :
> Merci Fred !
>
> Je vais abuser de ta gentillesse pour ma culture et mon edification :
> tres =(double **)ckalloc((nseq+1)*sizeof(double *));
> for (i=0; i<nseq; i++) {
> tres[i] = (double *)ckalloc((nseq+1)*sizeof(double));
> }
> tres[nseq] = NULL;
>
> J'alloue un pointeur de pointeur. J'en alloue nseq+1

Plus exactement tu alloues un tableau de nseq pointeurs sur des tableaux
de nseq doubles. Une matrice nseq x nseq en gros.

Au passage le dernier élément de chaque tableau est inutile compte tenu
du code. Du coup tu peux réécrire comme suit :

tres =(double **)ckalloc(nseq*sizeof(double *));
for (i=0; i<nseq; i++) {
tres[i] = (double *)ckalloc(nseq*sizeof(double));
}

> Quand on desalloue,
> for (i=0; i<nseq; i++) {
> ckfree((char *)tres[i]);
> }
> ckfree((char *)tres);
>
> J'en desalloue nseq, et le dernier ckfree desalloue le nseq+1 ieme.

Ca désalloue tous les sous-tableaux du tableau principal puis le tableau
principal. Le code est correct est dans le bon ordre (toujours libérer
le contenu avant le contenant).

> Ou bien un seul ckfree() va desallouer tout le monde ?

Un seul ckfree ne désallouera que le tableau principal, donc tu auras
des fuites mémoire. Il faut toujours un appel à free par appel à alloc.

> Tant que j'y suis, ne faut-il pas desallouer le tableau de Tcl_Obj **Lseq ?

Non car il appartient à l'objet liste (objv[1]).

> Merci de m'éclairer !!
> Luc
>

De rien !

A++, Fred
0 new messages