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

Problème avec __func__

14 réponses
Avatar
smu
Bonjour,

J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.
Afin de tracer l'usage de l'API chez nos clients (en déverminage), j'ai
utilisé une macro que j'avais trouvé sur la toile :

#ifndef __func__
#ifdef __FUNCTION__
#define __func__ __FUNCTION__
#else
#ifdef __FUNC__
#define __func__ __FUNC__
#else
#define __func__ "<unknow>"
#endif
#endif
#endif

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction (il semble accessible sous la forme d'une
variable local de type ''static const char __func__[];'').

Du coup, je recherche une solution pour remplacer la macro initiale.

D'avance merci pour tout élément qui ferait avancé le schmilblick.

smu

10 réponses

1 2
Avatar
espie
In article <et3l9t$33u$, smu wrote:
Bonjour,

J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.
Afin de tracer l'usage de l'API chez nos clients (en déverminage), j'ai
utilisé une macro que j'avais trouvé sur la toile :

#ifndef __func__
#ifdef __FUNCTION__
#define __func__ __FUNCTION__
#else
#ifdef __FUNC__
#define __func__ __FUNC__
#else
#define __func__ "<unknow>"
#endif
#endif
#endif

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction (il semble accessible sous la forme d'une
variable local de type ''static const char __func__[];'').


Oui, c'est du C99...
Tu peux te rabattre sur
#ifdef __STDC_VERSION__
# if __STDC_VERSION__ >= 199901L
...
# endif
#endif

pour t'assurer que __func__ est bien definie `correctement'. Sinon,
ben tu vas retomber sur du pre-standard, et ca va etre un peu n'importe
quoi...

Avatar
Antoine Leca
smu wrote:
J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.


Hmmm, comme le fait remarquer Marc, si tu utilises du C99 (__func__) sur de
multiples compilateurs, tu devrais te proteger avec __STDC_VERSION__... mais
bon c'est du cosmétique.


Afin de tracer l'usage de l'API chez nos clients (en déverminage),
j'ai utilisé une macro que j'avais trouvé sur la toile :
<couic>

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction


Euh oui, le nom de la fonction en cours de définition n'est accessible qu'à
l'intérieur de la définition ; quand on y réfléchit, on a du mal à voir
comment faire autrement, d'ailleurs.

Du coup, je recherche une solution pour remplacer la macro initiale.


Peut-être pourrais-tu exprimer le besoin que tu cherches à combler (imprimer
quoi, dans quel contexte, dans quelles conditions le problème se manifeste où la solution actuelle plante-t-elle et comment ?)


Antoine

Avatar
smu
smu wrote:
J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.


Hmmm, comme le fait remarquer Marc, si tu utilises du C99 (__func__) sur de
multiples compilateurs, tu devrais te proteger avec __STDC_VERSION__... mais
bon c'est du cosmétique.



Le problème est que je suis en présence de multiples compilateurs qui ne
sont pas tous conforme au standard C99.


Afin de tracer l'usage de l'API chez nos clients (en déverminage),
j'ai utilisé une macro que j'avais trouvé sur la toile :
<couic>

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction


Euh oui, le nom de la fonction en cours de définition n'est accessible qu'à
l'intérieur de la définition ; quand on y réfléchit, on a du mal à voir
comment faire autrement, d'ailleurs.



Vu la déclaration sous-jacente, je comprends bien le problème de la
portée de l'identifiant __func__. Toutefois, la macro __FUNCTION__ de
GNU C et de Microsoft C n'était pas soumis à ce problème.

Du coup, je recherche une solution pour remplacer la macro initiale.


Peut-être pourrais-tu exprimer le besoin que tu cherches à combler (imprimer
quoi, dans quel contexte, dans quelles conditions le problème se manifeste > où la solution actuelle plante-t-elle et comment ?)



Le besoin est simple : afficher la pile d'appel lorsqu'une erreur se
produit.
La solution actuelle (voir macro) ne fonctionne pas puisque __func__
n'est pas défini à cet instant.


Antoine



smu


Avatar
espie
In article <et67et$ot7$, smu wrote:
smu wrote:
J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.


Hmmm, comme le fait remarquer Marc, si tu utilises du C99 (__func__) sur de
multiples compilateurs, tu devrais te proteger avec __STDC_VERSION__... mais
bon c'est du cosmétique.



Le problème est que je suis en présence de multiples compilateurs qui ne
sont pas tous conforme au standard C99.


Afin de tracer l'usage de l'API chez nos clients (en déverminage),
j'ai utilisé une macro que j'avais trouvé sur la toile :
<couic>

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction


Euh oui, le nom de la fonction en cours de définition n'est accessible qu'à
l'intérieur de la définition ; quand on y réfléchit, on a du mal à voir
comment faire autrement, d'ailleurs.



Vu la déclaration sous-jacente, je comprends bien le problème de la
portée de l'identifiant __func__. Toutefois, la macro __FUNCTION__ de
GNU C et de Microsoft C n'était pas soumis à ce problème.


Oui, mais tout ceci etait pre-standard 99.

Du coup, je recherche une solution pour remplacer la macro initiale.


Peut-être pourrais-tu exprimer le besoin que tu cherches à combler (imprimer
quoi, dans quel contexte, dans quelles conditions le problème se manifeste >> où la solution actuelle plante-t-elle et comment ?)



Le besoin est simple : afficher la pile d'appel lorsqu'une erreur se
produit.
La solution actuelle (voir macro) ne fonctionne pas puisque __func__
n'est pas défini à cet instant.


La solution est simple: si tu es C99, tu n'as pas a t'ennuyer avec tout ca,
et tu testes juste la valeur de __STDC_VERSION__...

Sinon, eh bien tu retombes sur le code que tu as deja... j'ai du mal a voir
ou est le probleme.



Avatar
smu
In article <et67et$ot7$, smu wrote:
smu wrote:
J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.
Hmmm, comme le fait remarquer Marc, si tu utilises du C99 (__func__) sur de

multiples compilateurs, tu devrais te proteger avec __STDC_VERSION__... mais
bon c'est du cosmétique.

Le problème est que je suis en présence de multiples compilateurs qui ne

sont pas tous conforme au standard C99.

Afin de tracer l'usage de l'API chez nos clients (en déverminage),
j'ai utilisé une macro que j'avais trouvé sur la toile :
<couic>

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction
Euh oui, le nom de la fonction en cours de définition n'est accessible qu'à

l'intérieur de la définition ; quand on y réfléchit, on a du mal à voir
comment faire autrement, d'ailleurs.

Vu la déclaration sous-jacente, je comprends bien le problème de la

portée de l'identifiant __func__. Toutefois, la macro __FUNCTION__ de
GNU C et de Microsoft C n'était pas soumis à ce problème.


Oui, mais tout ceci etait pre-standard 99.

Du coup, je recherche une solution pour remplacer la macro initiale.
Peut-être pourrais-tu exprimer le besoin que tu cherches à combler (imprimer

quoi, dans quel contexte, dans quelles conditions le problème se manifeste >>> où la solution actuelle plante-t-elle et comment ?)

Le besoin est simple : afficher la pile d'appel lorsqu'une erreur se

produit.
La solution actuelle (voir macro) ne fonctionne pas puisque __func__
n'est pas défini à cet instant.


La solution est simple: si tu es C99, tu n'as pas a t'ennuyer avec tout ca,
et tu testes juste la valeur de __STDC_VERSION__...

Sinon, eh bien tu retombes sur le code que tu as deja... j'ai du mal a voir
ou est le probleme.


Le problème est que je ne veux pas gérer du code pour les compilos C99
et du code pour les compilos non-C99.
De plus, ce n'est pas moins qui décide du compilo que les clients vont
utiliser.
C'est pour cela que je cherche une solution passe-partout.

smu




Avatar
Antoine Leca
smu wrote:
smu wrote:
J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.


Hmmm, comme le fait remarquer Marc, si tu utilises du C99 (__func__)
sur de multiples compilateurs, tu devrais te proteger avec
__STDC_VERSION__... mais bon c'est du cosmétique.


Le problème est que je suis en présence de multiples compilateurs qui
ne sont pas tous conforme au standard C99.


J'ai du mal à te suivre.
Tu définis conditionnellement __func__ (à __FUNCTION__ OU __FUNC__), la
condition étant que __STDC_VERSION__ soit inférieur à 199901L; si
__STDC_VERSION__ est supérieur à 199901L, *et* que __func__ ne se comporte
pas comme il faut, tu reportes (bruyamment) ton cas auprès du fournisseur de
compilateur (car il n'est pas conforme à la norme.) Si la condition est
vérifiée (cas de tes compilateurs non-conformes), tu auras par la suite un
"__func__" reconstruit (à __FUNCTION__ OU __FUNC__), à charge pour toi de
faire du mieux possible (test sur le numéro de version etc.) pour trouver un
remplaçant adapté.

Attention évidemment à ne pas tester par #if la #définition de __FUNCTION__
(ou de __func__, ou de n'importe quoi de similaire) hors d'un contexte de
fonction, car certains compilateurs vont effectivement faire la moue...
Autrement dit, il est sous-entendu que le morceau de code en direct
d'internet que tu as montré doit se trouver à l'*intérieur* d'une fonction,
peu importe que cette fonction soit utile, ou appelée, elle ne sert qu'à
établir le bon environnement pour les compilateurs.


Afin de tracer l'usage de l'API chez nos clients (en déverminage),
j'ai utilisé une macro que j'avais trouvé sur la toile :
<couic>

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction


Euh oui, le nom de la fonction en cours de définition n'est
accessible qu'à l'intérieur de la définition ; quand on y réfléchit,
on a du mal à voir comment faire autrement, d'ailleurs.


Vu la déclaration sous-jacente, je comprends bien le problème de la
portée de l'identifiant __func__. Toutefois, la macro __FUNCTION__ de
GNU C et de Microsoft C n'était pas soumis à ce problème.


?

C>type func.c
int printf(const char*, ...);

const char *dehors = __FUNCTION__;

int main() {
const char *ici=__FUNCTION__;
printf("ici=<%s>, dehors=<%s>;n", ici, dehors);
return 0; }

C>gcc -o gcc -W -Wall func.c

C>cl func.c
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

func.c
func.c(3) : error C2457: '__FUNCTION__': predefined macro cannot appear
outside
of a function body


Autrement dit, certes gcc accepte sans broncher la construction douteuse,
mais (une version pas spécialement récente) de VC tousse violement.


Du coup, je recherche une solution pour remplacer la macro initiale.


Peut-être pourrais-tu exprimer le besoin que tu cherches à combler
(imprimer quoi, dans quel contexte, dans quelles conditions le
problème se manifeste = où la solution actuelle plante-t-elle et
comment ?)



Le besoin est simple : afficher la pile d'appel lorsqu'une erreur se
produit.


Et c'est là que j'ai du mal.
Pour afficher la pile d'appel (un concept dynamique), il faut un outil
dynamique (normalement, les cadres de pile), donc ce ne peut pas être fait
seulement avec des outils statiques (= dépendent du seul compilateur) comme
peut l'être __func__ (ou __FUNCTION__ etc.)

La solution classique fait appel à un déboggeur post-mortem (core,
Dump/Minidump), lequel utilise pour ce faire des fichiers spéciaux (les «
symboles de débogage », Dwarf/PDB) qui font la liaison entre les adresses
d'exécution et les noms de fonction (et des tas d'autres
choses.)Malheureusement, il n'y a guère de standards inter-plateforme à ce
niveau, mais un embryon de réponse peut se trouver au niveau des fichiers de
sortie de l'édition des liens (.map)
Mais la seule information du nom de la fonction est clairement
insuffisante...


La solution actuelle (voir macro) ne fonctionne pas puisque __func__
n'est pas défini à cet instant.


Je persiste à ne pas comprendre comment tu arrives à cette situation de
non-fonctionnement. En fait, si j'arrive efectivement à reproduire un cas
d'erreur (cf. supra, et ce sans utiliser __func__), il n'en est pas moins
que mon exemple est stupide (qui voudrait obtenir le nom d'une fonction dans
la définition d'une variable globale ?)

Peut-être un petit exemple avec les messages d'erreur obtenu m'aiderait à
comprendre un peu mieux.


Antoine



Avatar
Antoine Leca
smu wrote:
La solution actuelle (voir macro) ne fonctionne pas puisque __func__
n'est pas défini à cet instant.


La solution est simple: si tu es C99, tu n'as pas a t'ennuyer avec
tout ca, et tu testes juste la valeur de __STDC_VERSION__...

Sinon, eh bien tu retombes sur le code que tu as deja... j'ai du mal
a voir ou est le probleme.


Le problème est que je ne veux pas gérer du code pour les compilos C99
et du code pour les compilos non-C99.


???

Dans le cas actuel, tu as *déjà* du code spécifique (pour au moins trois
compilos différents). L'avantage d'un standard, c'est _justement_ de réduire
voire de supprimer le code à tiroir et les problèmes de maintenance qui en
résultent.
Ensuite, par rapport à simple standard lié à un succès commercial, une norme
apporte une définition précise des tenants et des aboutissants de chaque
construction, donc permet une meilleure prédiction au moment d'écrire la
code.

Ici, la construction standard c'est __func__ (c'est bien comme cela que tu
as nommé ta macro ;-)), et il se trouve qu'elle est définit par une norme.
Pour standardiser, c'est simple, utilise __func__ ou __STDC_VERSION__, comme
l'explique Marc, et suit les sémantiques normées de __func__. Sinon, tu
seras forcé à gérer *plusieurs* standards (ou pas standard), autrement dit
plusieurs codes...


De plus, ce n'est pas moins qui décide du compilo que les clients vont
utiliser.
C'est pour cela que je cherche une solution passe-partout.


Si tu ne veux plus de cet imbroglio, _et_ que tu maintiens ton besoin de
connaître les noms des fonctions, tu seras obligé de forcer tes clients à un
seul standard, et le choix est maigre : c'est soit C99 (norme officielle
depuis 7 ans), soit Microsoft (qui migre lentement vers C99), soit
éventuellement Borland/CodeGear (en fonction de sa base installée; en C je
ne pense pas que cela reste un vrai concurrent; migre très lentement vers
C99, ils manquent de ressources.) Dans tous les cas, tu vas te faire des
ennemis chez tes clients.
Désolé, cela ne passe donc pas partout... ce fut plus simple avec C90, c'est
vrai.

Qui plus est, la solution qui a le plus de visibilité à l'avenir, sur ce cas
précis comme en règle générale, c'est justement C99.


Maintenant, si tu veux une solution qui aille *au-delà* des possibilités de
C99 (ici, pouvoir utiliser __func__ en dehors d'une fonction), d'abord il te
faut définir précisemment tes besoins (au moins pour pouvoir les documenter
pour rendre possible la maintenance par la suite), et ensuite cela
resteindra forcémment la portabilité : ce sera tout sauf du standard.


J'ai par ailleurs remarqué que dans ce genre de cas, en général, l'analyse
fine permet de se rendre compte que le problème n'en est pas un. Mais c'est
vrai que parfois il faut alors reprendre le code précédent qui était fondé
sur une analyse incorrecte.


Antoine



Avatar
pas de nom
smu wrote:


smu wrote:

J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.


Hmmm, comme le fait remarquer Marc, si tu utilises du C99 (__func__)
sur de multiples compilateurs, tu devrais te proteger avec
__STDC_VERSION__... mais bon c'est du cosmétique.


Le problème est que je suis en présence de multiples compilateurs qui
ne sont pas tous conforme au standard C99.



J'ai du mal à te suivre.
Tu définis conditionnellement __func__ (à __FUNCTION__ OU __FUNC__), la
condition étant que __STDC_VERSION__ soit inférieur à 199901L; si
__STDC_VERSION__ est supérieur à 199901L, *et* que __func__ ne se comporte
pas comme il faut, tu reportes (bruyamment) ton cas auprès du fournisseur de
compilateur (car il n'est pas conforme à la norme.) Si la condition est
vérifiée (cas de tes compilateurs non-conformes), tu auras par la suite un
"__func__" reconstruit (à __FUNCTION__ OU __FUNC__), à charge pour toi de
faire du mieux possible (test sur le numéro de version etc.) pour trouver un
remplaçant adapté.

Attention évidemment à ne pas tester par #if la #définition de __FUNCTION__
(ou de __func__, ou de n'importe quoi de similaire) hors d'un contexte de
fonction, car certains compilateurs vont effectivement faire la moue...
Autrement dit, il est sous-entendu que le morceau de code en direct
d'internet que tu as montré doit se trouver à l'*intérieur* d'une fonction,
peu importe que cette fonction soit utile, ou appelée, elle ne sert qu'à
établir le bon environnement pour les compilateurs.



Afin de tracer l'usage de l'API chez nos clients (en déverminage),
j'ai utilisé une macro que j'avais trouvé sur la toile :


<couic>

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction


Euh oui, le nom de la fonction en cours de définition n'est
accessible qu'à l'intérieur de la définition ; quand on y réfléchit,
on a du mal à voir comment faire autrement, d'ailleurs.


Vu la déclaration sous-jacente, je comprends bien le problème de la
portée de l'identifiant __func__. Toutefois, la macro __FUNCTION__ de
GNU C et de Microsoft C n'était pas soumis à ce problème.



?

C>type func.c
int printf(const char*, ...);

const char *dehors = __FUNCTION__;

int main() {
const char *ici=__FUNCTION__;
printf("ici=<%s>, dehors=<%s>;n", ici, dehors);
return 0; }

C>gcc -o gcc -W -Wall func.c

C>cl func.c
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

func.c
func.c(3) : error C2457: '__FUNCTION__': predefined macro cannot appear
outside
of a function body


Autrement dit, certes gcc accepte sans broncher la construction douteuse,
mais (une version pas spécialement récente) de VC tousse violement.



Du coup, je recherche une solution pour remplacer la macro initiale.


Peut-être pourrais-tu exprimer le besoin que tu cherches à combler
(imprimer quoi, dans quel contexte, dans quelles conditions le
problème se manifeste = où la solution actuelle plante-t-elle et
comment ?)



Le besoin est simple : afficher la pile d'appel lorsqu'une erreur se
produit.



Et c'est là que j'ai du mal.
Pour afficher la pile d'appel (un concept dynamique), il faut un outil
dynamique (normalement, les cadres de pile), donc ce ne peut pas être fait
seulement avec des outils statiques (= dépendent du seul compilateur) comme
peut l'être __func__ (ou __FUNCTION__ etc.)

La solution classique fait appel à un déboggeur post-mortem (core,
Dump/Minidump), lequel utilise pour ce faire des fichiers spéciaux (les «
symboles de débogage », Dwarf/PDB) qui font la liaison entre les adresses
d'exécution et les noms de fonction (et des tas d'autres
choses.)Malheureusement, il n'y a guère de standards inter-plateforme à ce
niveau, mais un embryon de réponse peut se trouver au niveau des fichiers de
sortie de l'édition des liens (.map)
Mais la seule information du nom de la fonction est clairement
insuffisante...



Sachant que 99% des erreurs proviennent d'une mauvaise séquence
d'initialisation des cartes (hardware), l'information des fonctions
appellées suffit.



La solution actuelle (voir macro) ne fonctionne pas puisque __func__
n'est pas défini à cet instant.



Je persiste à ne pas comprendre comment tu arrives à cette situation de
non-fonctionnement. En fait, si j'arrive efectivement à reproduire un cas
d'erreur (cf. supra, et ce sans utiliser __func__), il n'en est pas moins
que mon exemple est stupide (qui voudrait obtenir le nom d'une fonction dans
la définition d'une variable globale ?)

Peut-être un petit exemple avec les messages d'erreur obtenu m'aiderait à
comprendre un peu mieux.



L'exemple suivant fonctionne très bien avec VS 2003 (L2) :

#include <stdio.h>

#define __label__ "L1"
#ifndef __func__
# ifdef __FUNCTION__
# define __func__ __FUNCTION__
# undef __label__
# define __label__ "L2"
# else
# ifdef __FUNC__
# define __func__ __FUNC__
# undef __label__
# define __label__ "L3"
# else
# define __func__ "<unknow>"
# undef __label__
# define __label__ "L4"
# endif
# endif
#endif

void testFunction(void)
{
printf("We are in function %sn", __func__);
printf("The %s method was detected.n", __label__);
}

int main(int argc, char * argv[])
{
testFunction();
return 0;
}


Antoine



smu




Avatar
smu
smu wrote:


smu wrote:

J'ai une API qui est compilé sur différentes plate-formes avec
différents compilateurs.


Hmmm, comme le fait remarquer Marc, si tu utilises du C99 (__func__)
sur de multiples compilateurs, tu devrais te proteger avec
__STDC_VERSION__... mais bon c'est du cosmétique.


Le problème est que je suis en présence de multiples compilateurs qui
ne sont pas tous conforme au standard C99.



J'ai du mal à te suivre.
Tu définis conditionnellement __func__ (à __FUNCTION__ OU __FUNC__), la
condition étant que __STDC_VERSION__ soit inférieur à 199901L; si
__STDC_VERSION__ est supérieur à 199901L, *et* que __func__ ne se comporte
pas comme il faut, tu reportes (bruyamment) ton cas auprès du fournisseur de
compilateur (car il n'est pas conforme à la norme.) Si la condition est
vérifiée (cas de tes compilateurs non-conformes), tu auras par la suite un
"__func__" reconstruit (à __FUNCTION__ OU __FUNC__), à charge pour toi de
faire du mieux possible (test sur le numéro de version etc.) pour trouver un
remplaçant adapté.

Attention évidemment à ne pas tester par #if la #définition de __FUNCTION__
(ou de __func__, ou de n'importe quoi de similaire) hors d'un contexte de
fonction, car certains compilateurs vont effectivement faire la moue...
Autrement dit, il est sous-entendu que le morceau de code en direct
d'internet que tu as montré doit se trouver à l'*intérieur* d'une fonction,
peu importe que cette fonction soit utile, ou appelée, elle ne sert qu'à
établir le bon environnement pour les compilateurs.



Afin de tracer l'usage de l'API chez nos clients (en déverminage),
j'ai utilisé une macro que j'avais trouvé sur la toile :


<couic>

Je viens de me rendre compte d'un problème, __func__ semble n'être
valide que dans la fonction


Euh oui, le nom de la fonction en cours de définition n'est
accessible qu'à l'intérieur de la définition ; quand on y réfléchit,
on a du mal à voir comment faire autrement, d'ailleurs.


Vu la déclaration sous-jacente, je comprends bien le problème de la
portée de l'identifiant __func__. Toutefois, la macro __FUNCTION__ de
GNU C et de Microsoft C n'était pas soumis à ce problème.



?

C>type func.c
int printf(const char*, ...);

const char *dehors = __FUNCTION__;

int main() {
const char *ici=__FUNCTION__;
printf("ici=<%s>, dehors=<%s>;n", ici, dehors);
return 0; }

C>gcc -o gcc -W -Wall func.c

C>cl func.c
Microsoft (R) 32-bit C/C++ Standard Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

func.c
func.c(3) : error C2457: '__FUNCTION__': predefined macro cannot appear
outside
of a function body


Autrement dit, certes gcc accepte sans broncher la construction douteuse,
mais (une version pas spécialement récente) de VC tousse violement.



Du coup, je recherche une solution pour remplacer la macro initiale.


Peut-être pourrais-tu exprimer le besoin que tu cherches à combler
(imprimer quoi, dans quel contexte, dans quelles conditions le
problème se manifeste = où la solution actuelle plante-t-elle et
comment ?)



Le besoin est simple : afficher la pile d'appel lorsqu'une erreur se
produit.



Et c'est là que j'ai du mal.
Pour afficher la pile d'appel (un concept dynamique), il faut un outil
dynamique (normalement, les cadres de pile), donc ce ne peut pas être fait
seulement avec des outils statiques (= dépendent du seul compilateur) comme
peut l'être __func__ (ou __FUNCTION__ etc.)

La solution classique fait appel à un déboggeur post-mortem (core,
Dump/Minidump), lequel utilise pour ce faire des fichiers spéciaux (les «
symboles de débogage », Dwarf/PDB) qui font la liaison entre les adresses
d'exécution et les noms de fonction (et des tas d'autres
choses.)Malheureusement, il n'y a guère de standards inter-plateforme à ce
niveau, mais un embryon de réponse peut se trouver au niveau des fichiers de
sortie de l'édition des liens (.map)
Mais la seule information du nom de la fonction est clairement
insuffisante...



Sachant que 99% des erreurs proviennent d'une mauvaise séquence
d'initialisation des cartes (hardware), l'information des fonctions
appellées suffit.



La solution actuelle (voir macro) ne fonctionne pas puisque __func__
n'est pas défini à cet instant.



Je persiste à ne pas comprendre comment tu arrives à cette situation de
non-fonctionnement. En fait, si j'arrive efectivement à reproduire un cas
d'erreur (cf. supra, et ce sans utiliser __func__), il n'en est pas moins
que mon exemple est stupide (qui voudrait obtenir le nom d'une fonction dans
la définition d'une variable globale ?)

Peut-être un petit exemple avec les messages d'erreur obtenu m'aiderait à
comprendre un peu mieux.



L'exemple suivant fonctionne très bien avec VS 2003 (L2) parce que
__FUNCTION__ existe même s'il renvoie qu'une chaîne vide :

#include <stdio.h>

#define __label__ "L1"
#ifndef __func__
# ifdef __FUNCTION__
# define __func__ __FUNCTION__
# undef __label__
# define __label__ "L2"
# else
# ifdef __FUNC__
# define __func__ __FUNC__
# undef __label__
# define __label__ "L3"
# else
# define __func__ "<unknow>"
# undef __label__
# define __label__ "L4"
# endif
# endif
#endif

void testFunction(void)
{
printf("We are in function %sn", __func__);
printf("The %s method was detected.n", __label__);
}

int main(int argc, char * argv[])
{
testFunction();
return 0;
}


Antoine



smu




Avatar
Antoine Leca
smu wrote:
Peut-être un petit exemple avec les messages d'erreur obtenu
m'aiderait à comprendre un peu mieux.


L'exemple suivant fonctionne très bien avec VS 2003 (L2) parce que
__FUNCTION__ existe même s'il renvoie qu'une chaîne vide :


Je ne suis pas sûr de bien comprendre tes messages. Jusqu'à maintenant, j'ai
vu un morceau de code qui, selon toi, marche. Et des récriminations comme
quoi « __func__ n'est pas défini », sans précision du compilateur.


#include <stdio.h>

#define __label__ "L1"
#ifndef __func__


Ajoute _avant_ cette ligne:

#if __STDC_VERSION__>9901L && !defined __func__
#define __func__ __func__ /* Rend le __func__ interne d'un compilo
* C99 visible depuis le préprocesseur */
#endif


Cela devrait permettre à ton code existant de passer plus ou moins sur un
compilo C99. Mais il n'en reste pas moins que la logique de test, au travers
du préprocesseur, d'une fonctionnalité qui n'en dépend pas (le préprocesseur
passe _avant_ que le translateur ne découpe le source en fonction) montre un
problème de logique de conception. Je ne serais pas surpris que des
compilateurs un peu pointilleux ne grognent (avertissement) sur le code
ci-dessus; de la même façon que d'écrire
#define int int
n'est pas un vrai problème dans la pratique, mais cela ne paraît pas très
propre non plus.


Antoine


1 2