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

strcmp et pointeur nul

32 réponses
Avatar
Seb
Bonjour,

On m'a demandé de porter du vieux code C depuis une machine HP vers du
Redhat 9. Je me trouve confronté à un étrange problème :

Dans le code (qui est en production), il y a souvent des "strcmp(<chaine>,
<null>)". Et cela fait planter mon appli : J'ai regardé dans le man du
strcmp et on ne parle pas de ce cas. Est ce un comportement normal ?

Sébastien

10 réponses

1 2 3 4
Avatar
Seb
"Alexandre BACQUART" a écrit dans le message news:
40b5ceb2$0$3203$
Seb wrote:
J'ai été certainement trop rapide : quand je disais que j'avais un
NULL ce n'est pas explicitement écrit c'est qu'un char* vaut 0 au
moment de l'éxecution.


Je me demandais justement comment ton compilo pouvait accepter ça...

Ben heu... tu as un plus gros problème, sans les sources, on peut pas
t'aider.


Et bien j'ai 280 strcmp / strcpy disséminé dans mon source et je dois les
sécuriser : c'est la problématique.

C'est une liste chainée d'éléments qui peuvent contenir des char* vides ou
pas qui sont utilisés avec mes str*, alors je pense que je vais d'abord
vérifier si ça ne viens pas de mes variables puis sécuriser manuellement les
str* qui sont dangereux.


Merci pour toutes vos réponses.

Sébastien


Avatar
Marc Boyer
Gaël Le Mignot wrote:
Inverser le #define et la défintion de la fonction me semble plus
sage, sinon elle va se rappeller elle-même indéfiniment... le return
strcmp(s1,s2); se transformant en return robust_strcmp(s1,s2);


Surtout, AMHA, il faut mettre les deux dans différents fichiers.
On peut remplacer les <string.h> par "hp-like-string.h" et faire
le #include <string.h> dans le hp-like-string.h, avec le
#define, ou décider de faire un "string-hp-patch", qui doit
être inclus après <string.h>...

Ce genre de chose.

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...

Avatar
Marc Boyer
Alexandre BACQUART wrote:
Gaël Le Mignot wrote:
int robust_strcmp(const char s1[], const char s2[]){
if (s1 == s2 ){ // Cas NULL == NULL



Commentaire faux et superflu.


Pourquoi faux ? Si la sémantique du hp-strcmp est que
hp-strcmp(0,0) == 0, c'est ce que cela doit faire.

Il y a aussi le problème que strcmp peut déjà être une macro. Dans ce
cas, il suffit de faire #undef strcmp avant.


#ifdef strcmp
#undef strcmp
#endif

Mais tromper comme ça le
compilo pour lui faire avaler du code incensé reste potentiellement
dangereux à mon avis...


Voui, je crois que j'avais appelé ça la méthode "rapide et sale".

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...



Avatar
Horst Kraemer
On Thu, 27 May 2004 11:47:24 +0200, "Seb" wrote:

"Alexandre BACQUART" a écrit dans le message news:
40b5b887$0$3204$
Seb wrote:

Bonjour,

Dans le code (qui est en production), il y a souvent des
"strcmp(<chaine>, <null>)". Et cela fait planter mon appli : J'ai
regardé dans le man du strcmp et on ne parle pas de ce cas. Est ce
un comportement normal ?


Déjà, strcmp(<chaine>, <null>), ça ne compile pas. Si tu veux dire que
le premier est un char* ou const char* et que le second est 0 (ou
NULL à l'ancienne), alors le plantage est normal, car je ne pense pas
qu'il y ait beaucoup d'implémentations de strcmp() qui perdent du
temps à vérifier la validité des pointeurs qu'on leur donne (et dans
tous les cas, l'expression perd tout son sens).


Oui tu as compris ma "syntaxe" :-)

Et bien le vieux compilateur HP semble faire le test, et malheureusement
pour moi j'ai des centaines de strcmp qui sont potentiellement "buggés". Si
vous avez une solution rapide ça m'aiderait bien


C'est un problème connu dû à l'implémentation de strcmp dans les
vielles bibliothèques glibc qui donnaient apparemment le résultat que
le programmeur attendait bien que

strcmp(machaine,0)

n'ait pas de sens selon la norme du langage C. Après l'avènement de
glibc 2, tous ces strcmp(chaine,0) plantaient...

Le problème est que les vieilles bibliothèques traitaient 0 comme une
"chaine vide", c,a,d, de la même facon qu'un pointeur valide qui
pointe vers le caractère .

Maitenant il y a deux possibilités de représenter "logiquement" une
chaine vide dans un programme C. Ou bien par 0 (ou NULL) ou bien par
la chaine "".

Quand il la représente toujours par un pointeur nul (0 ou NULL) il n'a
jamais besoin de strcmp et un programmeur intelligent n'utiliserait
jamais

if (!strcmp(machaine,0));

mais

if (machaine)
ou
if (machaine!=NULL)


Quand il représente une chaine vide par "", alors

if (!strcmp("",0));

fonctionnait (par hasard ou plutot par définition de cette
bibliothèque) et disait "égal", et on devrait remplacer partout

strcmp(machaine,0));

par

strcmp(machaine,""));


pour corriger le code. Le vrai problème est que les deux

strcmp(0, 0);
strcmp("",0);

fonctionnaient avec les vieilles bibliothèques et disaient "égal" et
que le programmeur pouvait utiliser les deux versions "logiques" de
"chaine vide" à la fois ;-)


Je crois que la "bonne" correction (qui inclut le cas où le
programmeur passe intentionellement machaine==NULL) serait donc

(machaine!=NULL && strcmp(machaine,""))

qui renvoie 1 si et seulement si machaine n'est pas NULL et ne pointe
pas vers une "vraie" chaine vide.


--
Horst



Avatar
Seb
"Horst Kraemer" a écrit dans le message news:

On Thu, 27 May 2004 11:26:49 +0200, "Seb" wrote:

Bonjour,

On m'a demandé de porter du vieux code C depuis une machine HP vers
du Redhat 9. Je me trouve confronté à un étrange problème :

Dans le code (qui est en production), il y a souvent des
"strcmp(<chaine>, <null>)". Et cela fait planter mon appli : J'ai
regardé dans le man du strcmp et on ne parle pas de ce cas. Est ce
un comportement normal ?


Oui. Parfaitement normal. Le comportement d'un appel de strcmp avec un
pointeur nul est indéfini. Le code n'a pas de sens.


Par curiosité je suis allé voir les man du Hp Unix

Et on peut lire ceci :

strcmp() Compares its arguments and returns an integer less
than, equal to, or greater than zero, depending on
whether s1 is lexicographically less than, equal to, or
greater than s2. The comparison of corresponding
characters is done as if the type of the characters
were unsigned char. Null pointer values for s1 and s2
are treated the same as pointers to empty strings.

La conclusion : c'était légal il y a un certain temps ....

Sébastien


Avatar
Marc Boyer
Horst Kraemer wrote:
pour corriger le code. Le vrai problème est que les deux

strcmp(0, 0);
strcmp("",0);

fonctionnaient avec les vieilles bibliothèques et disaient "égal" et
que le programmeur pouvait utiliser les deux versions "logiques" de
"chaine vide" à la fois ;-)


Ah, j'avais mal deviné la sémantique du truc.

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...

Avatar
Yves ROMAN

Alexandre BACQUART wrote:
Gaël Le Mignot wrote:
int robust_strcmp(const char s1[], const char s2[]){
if (s1 == s2 ){ // Cas NULL == NULL



Commentaire faux et superflu.


Pourquoi faux ? Si la sémantique du hp-strcmp est que
hp-strcmp(0,0) == 0, c'est ce que cela doit faire.



Cela traite aussi le cas ou on compare une variable avec elle-même : on évite
alors un strcmp() :
char toto[] = "coucou"
robust_strcmp(toto,toto) ;




Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Seb" wrote:

On m'a demandé de porter du vieux code C depuis une machine HP vers du
Redhat 9. Je me trouve confronté à un étrange problème :

Dans le code (qui est en production), il y a souvent des "strcmp(<chaine>,
<null>)". Et cela fait planter mon appli : J'ai regardé dans le man du
strcmp et on ne parle pas de ce cas. Est ce un comportement normal ?


Passer NULL à strcmp() invoque un comportement indéterminé. Il ne fait pas
faire ça. C'est un bug qu'il faut corriger d'urgence.

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?libÉ9
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Seb" wrote:

Et bien le vieux compilateur HP semble faire le test, et malheureusement
pour moi j'ai des centaines de strcmp qui sont potentiellement "buggés". Si
vous avez une solution rapide ça m'aiderait bien


Quelle signification peut bien avoir strcmp ("yadyada, NULL) ? C'est plutôt
bizarre comme code... Que retourne le strcmp() de HP dans ce cas là ?

Sinon, on peut remplacer les strcmp() du code par my_strcmp() qui fait par
exemple (ça peut se faire de façon 'invisible') avec une macro :

#ifndef STRCMP_H
#define STRCMP_H
/* mystrcmp.h */

/* pour garantir l'ordre d'inclusion qui a son
* importance quand on definit une macro qui a
* le nom d'une fonction connue.
*/
#include <string.h>

#define strcmp(a, b) my_strcmp (a, b)
int my_strcmp (char const *s1, char const *s2);
#endif /* guard */

/* mystrcmp.c */
#include "mystrcmp.h"
/* NE RIEN METTRE ICI.
* IMPORTANT SINON TOUT EXPLOSE!
*/
#undef strcmp

int my_strcmp (char const *s1, char const *s2)
{
int ret = 0; /* la valeur qui va bien... */

if (s1 != NULL && s2 != NULL)
{
ret = strcmp(s1, s2);
}
return ret;
}

*** NON TESTE ***

mais c'est quand même de la grosse bidouille...

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?libÉ9
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', Alexandre BACQUART wrote:

Seb wrote:
J'ai été certainement trop rapide : quand je disais que j'avais un NULL ce
n'est pas explicitement écrit c'est qu'un char* vaut 0 au moment de
l'éxecution.


Je me demandais justement comment ton compilo pouvait accepter ça...


Il s'en tape!

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?libÉ9
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/


1 2 3 4