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

Marquage des infos de debogage

18 réponses
Avatar
candide
Bonjour,

Je suis confronté à un phénomène très curieux.

Ça se passe sous Linux Ubuntu HH, avec gcc et gdb. En bref, j'ai deux fichiers
source, que j'ai tenté de réduire au minimum pour que mon problème demeure
reproductible.

L'un, une fois compilé avec gcc -g peut me montrer les infos de débogage MAIS si
j'ampute le fichier source de quelques caractères non imprimables (saut de ligne
et espaces), quand je compile avec gcc -g, plus aucune info de débogage lisible.

Avez-vous déjà rencontré ça ?

Je précise que le même fichier pose les mêmes problèmes sous Windows compilé
avec Mingw (gcc pour Windows). Par contre, sous Visual, le débogueur fonctionne.
Je n'ai pas essayé avec d'autres compilateurs genre Open Watcom.

Mes sources sont en UTF-8.

Plus précisément, voici les sources et les symptomes (copies de console) :

-------- a_deboguerOUI.c --------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }}
---------------------------------------------------------------

candide@candide-desktop:~$ gcc -g -W -Wall -std=c99 -pedantic -o x a_deboguerOUI.c
candide@candide-desktop:~$ ./x
candide@candide-desktop:~$ gdb x
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) list
1 /*^Mint f(int b)^M{^M ^M}^M*/^Mint main(void)^M{ ^M return 0;^M}
(gdb)

ceci est le source dans un éditeur hexa :

0000:0000 2f 2a 0d 69 6e 74 20 66 28 69 6e 74 20 62 29 0d /*.int f(int b).
0000:0010 7b 0d 20 0d 7d 0d 2a 2f 0d 69 6e 74 20 6d 61 69 {. .}.*/.int mai
0000:0020 6e 28 76 6f 69 64 29 0d 7b 20 0d 20 20 20 20 72 n(void).{ . r
0000:0030 65 74 75 72 6e 20 30 3b 0d 7d 0d 0a eturn 0;.}..

-------- a_deboguerNON.c --------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }
---------------------------------------------------------------

candide@candide-desktop:~$ gcc -g -W -Wall -std=c99 -pedantic -o x a_deboguerNO.c
candide@candide-desktop:~$ gdb x
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) list
Line number 2

Le code hexa du 2ème source :

0000:0000 2f 2a 0d 69 6e 74 20 66 28 69 6e 74 20 62 29 0d /*.int f(int b).
0000:0010 7b 0d 20 0d 7d 0d 2a 2f 0d 69 6e 74 20 6d 61 69 {. .}.*/.int mai
0000:0020 6e 28 76 6f 69 64 29 0d 7b 20 0d 0d 0d 20 20 20 n(void).{ ...
0000:0030 20 72 65 74 75 72 6e 20 30 3b 0d 7d 0d 0a return 0;.}..


Quelqu'un a-t-il une petite idée d'explication ?

Merci d'avance

10 réponses

1 2
Avatar
Antoine Leca
Le 27/02/2009 13:27, candide écrivit :
Ça se passe sous Linux Ubuntu HH, avec gcc et gdb. [...]
Je précise que le même fichier pose les mêmes problèmes sous Windows compilé
avec Mingw (gcc pour Windows). Par contre, sous Visual, le débogueur fonctionne.



Donc, à vue de nez un problème lié à un outil en particulier,
probablement GDB.


Mes sources sont en UTF-8.



Heu ? Désolé mais je n'ai pas vu à quel endroit il y avait des
caractères étendus dans ton source.

Donc je vais supposer que tes sources sont en ASCII, d'accord.


Plus précisément, voici les sources et les symptomes (copies de console) :

-------- a_deboguerOUI.c --------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }}
-------- a_deboguerNON.c --------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }
---------------------------------------------------------------



Ah... Moi j'aurais bien compris si cela avait été le contraire... (la
double accolade à la fin, toussa)


ceci est le source dans un éditeur hexa :
0000:0000 2f 2a 0d 69 6e 74 20 66 28 69 6e 74 20 62 29 0d /*.int f(int b).
0000:0010 7b 0d 20 0d 7d 0d 2a 2f 0d 69 6e 74 20 6d 61 69 {. .}.*/.int mai
0000:0020 6e 28 76 6f 69 64 29 0d 7b 20 0d 20 20 20 20 72 n(void).{ . r
0000:0030 65 74 75 72 6e 20 30 3b 0d 7d 0d 0a eturn 0;.}..
Le code hexa du 2ème source :
0000:0000 2f 2a 0d 69 6e 74 20 66 28 69 6e 74 20 62 29 0d /*.int f(int b).
0000:0010 7b 0d 20 0d 7d 0d 2a 2f 0d 69 6e 74 20 6d 61 69 {. .}.*/.int mai
0000:0020 6e 28 76 6f 69 64 29 0d 7b 20 0d 0d 0d 20 20 20 n(void).{ ...


^^ ^^
0000:0030 20 72 65 74 75 72 6e 20 30 3b 0d 7d 0d 0a return 0;.}..



La seule différence sont les deux CR en plus comme marqués, c'est bien
cela ? (deux trucs en passant : man cmp et HELP FC ; merci d'avance.)

Bon, alors là on est en plein dans le domaine de ce qui est « défini par
l'implémentation » (et sa doc) !
La norme (5.2.1) dit seulement que le source est présenté par des
caractères (y compris l'espace, les tabulations horizontales et
verticales et le saut de page, mais à l'exclusion de la sonnette ou des
retours en arrière ou en début de ligne), regroupées en lignes, mais ne
définit pas comment sont présentées les lignes, ni même s'il existe un
ou des caractères *source* pour saut-de-ligne. Par exemple, sur une des
machines ici, le saut de ligne c'est lorsqu'on arrive à la colonne 80 de
la carte perforée.
Si une ligne est présentée de manière incorrecte pour le compilateur
(mauvaise convention de fins de ligne, NUL ou DEL de bourrage, etc.)
techniquement le comportement est indéfini, et dans la pratique il y a
pas mal de choix !

Sur une machine *nix classique, le saut de ligne c'est LF (0a), et en ce
qui concerne les CR présents dans le source c'est au bon plaisir du
compilo, soit on ignore, soit on recode comme saut de ligne, voire on
combine selon le contexte, en particulier en ce qui concerne les
séquences ; avec GCC et un source de ce genre (comme ceux qui viennent
d'environnement Macintosh ou MS-Basic), on a une indication grâce au
message « manque une fin de ligne à la fin » qui peut être émis si le
compilateur ne voit pas les CR comme fins de ligne... mais ici il y a
un 0a vicieux en fin de source qui cache cette précieuse indication. Qui
plus est, GDB peut avoir une logique différente de celle de GCC,
puisqu'il n'y a pas de norme établie
À mon avis, tu es donc dans le cas où il y a discorde pour une séquence
de caractères CR qui se suivent.

Sur les systèmes Windows et compagnie, le saut de ligne c'est CR+LF
comme dans ce message ; pour la compatibilité *nix, la grande majorité
des compilateurs acceptent les LF seuls comme équivalents ; par contre,
pour la compatibilité « Mac », on a là aussi des divergences : les
outils de provenance *nix (comme GCC) vont avoir tendance à reprendre le
schéma *nix tel quel (ce qui pourrait expliquer la reproductibilité avec
Mingw), tandis que d'autres peuvent avoir une plus grande compatibilité
; et le compilo C de Microsoft a fonctionné dans le passé avec des
sources Macintosh, en fait probablement fonctionne toujours d'ailleurs,
par exemple pour Office2008.


Maintenant, si la question est, faut-il remonter cela comme bogue aux
développeurs de GCC ou de GDB, d'abord je ne sais pas si ce jeu en vaut
la chandelle (vu que c'est UB et qu'il y a le 0a final qui cache le
warning), et d'autre part je pense qu'il y a d'autre forums probablement
plus adaptés (mais probablement en anglais), non ?


Antoine
Avatar
Jean-Marc Bourguet
candide writes:

Antoine Leca a écrit :
Le 27/02/2009 13:27, candide écrivit :



Donc, à vue de nez un problème lié à un outil en particulier,
probablement GDB.




Je suis hors charte tu veux dire ;) ? Mon problème est quand même lié
aussi à la façon d'encoder mon fichier source donc je suis pas tant hors
charte que ça. Mais j'ai l'impression que personne ne débogue ici.



Pourquoi? Je ne sais pas comment tu es arrivé à avoir des fichiers avec
les fins de ligne encodées comme ça. J'ai l'impression que l'explication
trop circonstantiée d'Antoine t'a perdu. Donc:

1/ coder les fins de lignes avec r n'est pas normal sous Unix

2/ gcc et gdb considèrent apparemment les r de manière différentes: gcc
comme étant des fins de ligne, gdb comme n'en étant pas. Les deux manières
ont une certaine cohérence (celle de gdb est la plus conforme à la
définition de fichier texte Unix, celle de gcc plus soucieuse de
portabilité).

3/ vu l'interprétation différente, la communication foire entre les deux.

4/ si tu avais essayé de débugger (avec start) même le fichier qui "marche"
d'après toi, tu aurais vu que tu as aussi un problème.

La seule différence sont les deux CR en plus comme marqués, c'est bien
cela ? (deux trucs en passant : man cmp et HELP FC ; merci d'avance.)



Oui, c'est bien ça, j'ai supprimé des retour chariot dans un fichier et ça
permet de lire les informations de débogage alors qu'avant c'était pas possible.



Par CR, Antoine désigne le caractère ASCII de code 13, pas un retour
chariot dans un sens plus générique de passage à la ligne.

Sous Unix, une fin de ligne s'indique par le caractère ASCII de code 10
(NL).

OK mais que faire en pratique pour ne pas avoir ce genre de discordance parce
que RIEN n'apparait à un examen visuel du source ?



Disons qu'avec l'éditeur que tu as choisi, rien ne paraît.

OK mais je pense que je ne suis pas le premier à rencontrer ce problème ici donc
si quelqu'un a un conseil _pratique_ à me donner je suis preneur (au passage,
n'en profitez pas pour essayer de me convertir à emacs ou vi ;) peine perdue
avec moi, je suis un mécréant !)



Pourtant, tous les deux indiquent clairement que ce que tu prends pour des
fins de ligne n'en est pas.

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
candide
Antoine Leca a écrit :
Le 27/02/2009 13:27, candide écrivit :



Donc, à vue de nez un problème lié à un outil en particulier,
probablement GDB.




Je suis hors charte tu veux dire ;) ? Mon problème est quand même lié aussi à la
façon d'encoder mon fichier source donc je suis pas tant hors charte que ça.
Mais j'ai l'impression que personne ne débogue ici.


Mes sources sont en UTF-8.



Heu ? Désolé mais je n'ai pas vu à quel endroit il y avait des
caractères étendus dans ton source.



Je dis juste, et à toutes fins utiles, dans quel format mon éditeur de texte
(gedit) me dit que le fichier est sauvegardé.


Donc je vais supposer que tes sources sont en ASCII, d'accord.


Plus précisément, voici les sources et les symptomes (copies de
console) :

-------- a_deboguerOUI.c --------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }}
-------- a_deboguerNON.c --------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }
---------------------------------------------------------------



Ah... Moi j'aurais bien compris si cela avait été le contraire... (la
double accolade à la fin, toussa)



Je reprends et je colle tel que Thunderbird l'accepte :

------------------a_deboguerOUI.c ------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }


------------------a_deboguerNO.c ------------------------------------
/* int f(int b) { } */ int main(void) { return 0; }



Bon, je sais, ça semble pareil mais ça vient pourtant de deux fichiers
différents et d'apparence différente dans mon éditeur de texte : le fichier
a_deboguerOUI.c a des sauts de ligne en moins par rapport à a_deboguerNO.c.

D'ailleurs, les code ci-dessus sont uper-bizarres :
1°) quand je le colle dans le lecteur, il sort en une seule ligne (alors que
dans mon source il tiennent sur 11 lignes et 13 lignes
2°) une fois collé dans le lecteur de news, si je place le point d'insertion
à la fin de chaque ligne de code ci-dessus et que je fais un retour chariot
(ENTRÉE quoi), normalement ça devrait faire une ligne vierge, et bien non, dans
les deux cas, ça coupe ma ligne, le premier avant l'accolade finale, le second
coupe le texte juste avant le 0, ça fait comme ceci

0;}

On dirait que l'encodage est complètement possédé ou pourri, le problème c'est
que rien n'est visible.



La seule différence sont les deux CR en plus comme marqués, c'est bien
cela ? (deux trucs en passant : man cmp et HELP FC ; merci d'avance.)



Oui, c'est bien ça, j'ai supprimé des retour chariot dans un fichier et ça
permet de lire les informations de débogage alors qu'avant c'était pas possible.

Et vu le message que me renvoie gdb lorsque je cherche à lire le source, c'est
bien un problème de saut de ligne :

(gdb) list
Line number 2 out of range; a_deboguerNO.c has 1 lines.



Si une ligne est présentée de manière incorrecte pour le compilateur
(mauvaise convention de fins de ligne, NUL ou DEL de bourrage, etc.)
techniquement le comportement est indéfini, et dans la pratique il y a
pas mal de choix !




OK, je veux bien mais pourquoi gcc ne me met aucun warning ?


À mon avis, tu es donc dans le cas où il y a discorde pour une séquence
de caractères CR qui se suivent.



OK mais que faire en pratique pour ne pas avoir ce genre de discordance parce
que RIEN n'apparait à un examen visuel du source ?


la chandelle (vu que c'est UB et qu'il y a le 0a final qui cache le
warning),



Pourquoi mon code est UB ?

et d'autre part je pense qu'il y a d'autre forums probablement
plus adaptés (mais probablement en anglais), non ?




OK mais je pense que je ne suis pas le premier à rencontrer ce problème ici donc
si quelqu'un a un conseil _pratique_ à me donner je suis preneur (au passage,
n'en profitez pas pour essayer de me convertir à emacs ou vi ;) peine perdue
avec moi, je suis un mécréant !)
Avatar
candide
candide a écrit :

OK mais je pense que je ne suis pas le premier à rencontrer ce problème ici donc
si quelqu'un a un conseil _pratique_ à me donner je suis preneur




Bon, j'essaye non pas de comprendre mais de faire en sorte que le problème ne se
reproduise pas :


alors, j'ai ouvert a_deboguerNO.txt dans Kate qui est quand même beaucoup moins
sommaire que gedit et j'ai vu que les fin de lignes étaient codées en format
Macinstosh !!! J'ai donc tout basculé en fin de ligne UNIX et boum! ça marche :


a_deboguerNO_.txt :

0000:0000 2f 2a 0a 69 6e 74 20 66 28 69 6e 74 20 62 29 0a /*.int f(int b).
0000:0010 7b 0a 20 0a 7d 0a 2a 2f 0a 69 6e 74 20 6d 61 69 {. .}.*/.int mai
0000:0020 6e 28 76 6f 69 64 29 0a 7b 20 0a 0a 0a 20 20 20 n(void).{ ...
0000:0030 20 72 65 74 75 72 6e 20 30 3b 0a 7d 0a return 0;.}.


(gdb) info source
Current source file is a_deboguerNO_.c
Compilation directory is /home/candide
Located in /home/candide/a_deboguerNO_.c
Contains 12 lines.
Source language is c.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.
(gdb)


et mon fichier a enfin retrouvé ses 12 lignes et non pas une seule comme avec le
précédent fichier.


C'est fou le temps qu'on est obligé de passer à ne pas faire du C quand on veut
en faire, c'est ça qu'il faudrait dire à ceux qui se lancent dans
l'apprentissage de ce langage.

Bref, ce que je retiens de tout ça, c'est que pour faire du C, il faut avoir un
éditeur de texte un peu évolué.
Avatar
candide
Antoine Leca a écrit :

Sur une machine *nix classique, le saut de ligne c'est LF (0a), et en ce
qui concerne les CR présents dans le source c'est au bon plaisir du
compilo, soit on ignore, soit on recode comme saut de ligne, voire on
combine selon le contexte, en particulier en ce qui concerne les
séquences ; avec GCC et un source de ce genre (comme ceux qui viennent
d'environnement Macintosh ou MS-Basic), on a une indication grâce au
message « manque une fin de ligne à la fin » qui peut être émis si le
compilateur ne voit pas les CR comme fins de ligne... mais ici il y a
un 0a vicieux en fin de source qui cache cette précieuse indication. Qui
plus est, GDB peut avoir une logique différente de celle de GCC,
puisqu'il n'y a pas de norme établie
À mon avis, tu es donc dans le cas où il y a discorde pour une séquence
de caractères CR qui se suivent.

Sur les systèmes Windows et compagnie, le saut de ligne c'est CR+LF
comme dans ce message ; pour la compatibilité *nix, la grande majorité
des compilateurs acceptent les LF seuls comme équivalents ; par contre,
pour la compatibilité « Mac », on a là aussi des divergences : les
outils de provenance *nix (comme GCC) vont avoir tendance à reprendre le
schéma *nix tel quel (ce qui pourrait expliquer la reproductibilité avec
Mingw), tandis que d'autres peuvent avoir une plus grande compatibilité
; et le compilo C de Microsoft a fonctionné dans le passé avec des
sources Macintosh, en fait probablement fonctionne toujours d'ailleurs,
par exemple pour Office2008.



Et à propos, merci Antoine, je crois que c'est grâce à tout ce que tu as dit là
que j'ai pensé à modifier les fins de ligne de mon source.
Avatar
-ed-
On 27 fév, 14:27, candide wrote:
ceci est le source dans un éditeur hexa :

0000:0000 2f 2a 0d 69 6e 74 20 66 28 69 6e 74 20 62 29 0d /*.int f(int b) .
0000:0010 7b 0d 20 0d 7d 0d 2a 2f 0d 69 6e 74 20 6d 61 69 {. .}.*/.int ma i
0000:0020 6e 28 76 6f 69 64 29 0d 7b 20 0d 20 20 20 20 72 n(void).{ .    r
0000:0030 65 74 75 72 6e 20 30 3b 0d 7d 0d 0a             etu rn 0;.}..

Le code hexa du 2ème source :

0000:0000 2f 2a 0d 69 6e 74 20 66 28 69 6e 74 20 62 29 0d /*.int f(int b) .
0000:0010 7b 0d 20 0d 7d 0d 2a 2f 0d 69 6e 74 20 6d 61 69 {. .}.*/.int ma i
0000:0020 6e 28 76 6f 69 64 29 0d 7b 20 0d 0d 0d 20 20 20 n(void).{ ...
0000:0030 20 72 65 74 75 72 6e 20 30 3b 0d 7d 0d 0a        return 0;.}..



Je ne comprends pas pourquoi il y a des 0d (^M) dans tes codes
sources. La fin de ligne sous unixoïde, c'est 0a. Ton format texte
n'est pas conforme. Le comportement est indéfini.
Avatar
-ed-
On 27 fév, 22:33, candide wrote:

Et oui, c'est pour ça que je vais prendre Kate qui est un peu moins som maire.
Sous codeBlocks (IDE, des trucs qui doivent t'être complètement étr angers), je
crois qu'on peut aussi régler les fin de lignes (CR, LF ou CRLF).



SI tu es amené à faire souvent du portage de sources entre Windows et
Linux, je recommande d'utiliser le format unixoïde pour tout le monde,
c'est à dire EOL = LF. Sous Windows, Code::Blocks le permet.
Avatar
Jean-Marc Bourguet
candide writes:

Jean-Marc Bourguet a écrit :

Pourquoi? Je ne sais pas comment tu es arrivé à avoir des fichiers avec
les fins de ligne encodées comme ça.



Moi non plus, peut-être des mélange de fichiers texte Linux et Windows.



Ni l'un ni l'autre utilise des CR seuls (Windows utilise des paires CR LF
-- je ne sais pas si c'est des séparateurs de lignes ou des marques de fin
de lignes, je ne suis même pas sûr que les programmes sous Windows sont
consistants). Je ne vois pas comment des transferts, même brutaux, peuvent
arriver à cette situation. Il faudrait mettre un Mac -- avec un OS 9 ou
antérieur vraisemblablement -- dans la boucle que ça devienne plausible.

GNU recode est capable de traiter ce genre de choses (section "Surfaces").

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
-ed-
On 27 fév, 22:33, candide wrote:
OK, donc en principe, sous Unix, je ne devrais pas avoir de problème si tous mes
sauts de lignes sont codés en 0a (alias LF ?). Et si par hasard j'ai du Od (ce
que je vois régulièrement dans mes fichiers), je change en 0a, c'est bon ?



Il n'y a aucune raison que tu ais des 0d 'par hasard'.

Soit tu es sous unixoïde, et un éditeur de texte ne met que des 0a en
fin de ligne, soit tu es sous DOS/Windows et là, un éditer de texte
met soit 0d0a (CRLF), car c'est la convention sous DOS/Windows
(réglage par défaut des éditeurs de textes), soit il met 0a, soit il
met 0d, parce qu'il sait le faire et qu'on lui a spécifiquement
demandé en agissant sur sa configuration. Pas de place pour le hasard.

Et si tu dois utiliser sous unixoïde, un fichier texte créé sous
Windows avec des CRLF (mode par défaut, je le rappelle), il faut,
avant de l'utiliser, le passer par une moulinette dos2unix en principe
disponible sur ces systèmes.

Mais je le répète, le plus simple est de tout faire au format
unixoïde, même sous Windows.

Si un outil Windows (ancien, probablement) n'accepte pas le format
unixoïde, en changer pour un outil plus moderne, ou alors utiliser
exceptionnellement unix2dos pour générer un fichier conforme.
Avatar
Patrick Texier
Le Sat, 28 Feb 2009 00:45:03 -0800 (PST), -ed- a écrit :

Mais je le répète, le plus simple est de tout faire au format
unixoïde, même sous Windows.



Oui. Le seul problème que je rencontre c'est patch qui demande des fins
de ligne Windows. Cela vient peut être de ma version (2.5.9 de 2003).
--
Patrick Texier

vim:syntax=mail:ai:ts=4:et:twr
1 2