OVH Cloud OVH Cloud

OutputDebugString style "sprintf"

46 réponses
Avatar
stat
Bonjour,

J'ai besoin d'aide pour creer une fonction de type OutputDebugString
qui envoit un message de debuggage mais qui soit aussi facile a
utiliser que printf c'est a dire que je puisse l'utiliser de la sorte

OutputDebugStringExt("Valeur x: %i, valeur y: %i, Nom: %s\n", x, y,
Nom);

et j'avoue ne pas savoir du tout comment m'y prendre

Avez-vous une idee pour commencer svp ?

Merci.

--
This is an automatic signature of MesNews.
Site : http://www.mesnews.net

10 réponses

1 2 3 4 5
Avatar
Loïc Joly
Bonjour,

J'ai besoin d'aide pour creer une fonction de type OutputDebugString qui
envoit un message de debuggage mais qui soit aussi facile a utiliser que
printf c'est a dire que je puisse l'utiliser de la sorte


Ne trouvant pas printf simple du tout à utiliser, je ne vais pas
forcément te donner une bonne solution. En particulier, je n'ai jamais
utilisé les va_arg ou les autres mécanismes pour les fonctions avec
nombre variable d'arguments, mais tu peux regarder de ce côté.

Je préfère largement les mécanismes à base de chaînage d'appels, comme :

OutputDebugStringExt << "Valeur x: " << x << ", valeur y: " << y
<< ", Nom: " << Nom << endl;

De plus, les mécanismes de ostream sont conçus dès le départ pour qu'on
puisse rediriger les sorties ailleurs.

--
Loïc

Avatar
Sylvain
stat wrote on 24/11/2006 11:10:
Bonjour,

J'ai besoin d'aide pour creer une fonction de type OutputDebugString qui
envoit un message de debuggage mais qui soit aussi facile a utiliser que
printf c'est a dire que je puisse l'utiliser de la sorte

OutputDebugStringExt("Valeur x: %i, valeur y: %i, Nom: %sn", x, y, Nom);
et j'avoue ne pas savoir du tout comment m'y prendre


simplement:

void OutputDebugStringExt(const char* pattern, ...)
{
// gain pointer to variable parameter list
va_list params;
va_start(params, pattern);
// format parameters according specified format
static char message[2048];
_vsnprintf(message, 2048, pattern, params);
// release parameter list
va_end(params);
// send message to loger
OutputDebugString(message);
}

évidemment c'est un feature de dubug, donc tu sais que les chaines
formattées ne dépassent jamais la longueur réservée (2048 ici)...

Sylvain.

Avatar
stat
1000 mercis !

--
This is an automatic signature of MesNews.
Site : http://www.mesnews.net
Avatar
James Kanze
Sylvain wrote:
stat wrote on 24/11/2006 11:10:

J'ai besoin d'aide pour creer une fonction de type OutputDebugString qui
envoit un message de debuggage mais qui soit aussi facile a utiliser que
printf c'est a dire que je puisse l'utiliser de la sorte

OutputDebugStringExt("Valeur x: %i, valeur y: %i, Nom: %sn", x, y, Nom );
et j'avoue ne pas savoir du tout comment m'y prendre


simplement:

void OutputDebugStringExt(const char* pattern, ...)
{
// gain pointer to variable parameter list
va_list params;
va_start(params, pattern);
// format parameters according specified format
static char message[2048];
_vsnprintf(message, 2048, pattern, params);
// release parameter list
va_end(params);
// send message to loger
OutputDebugString(message);
}

évidemment c'est un feature de dubug, donc tu sais que les chaines
formattées ne dépassent jamais la longueur réservée (2048 ici)...


Jusqu'elles le font. Pourquoi 2048, d'ailleurs ? Pourquoi pas
2000 ? Ou 10000 ?

De l'autre côté, il y a toujours le problème des types qui ne
conviennent pas. Printf et compagnie, c'est un core dump larvé.
Comme Loïc, je ne trouve pas la syntaxe de printf
particulièrement conviviable. Mais si on y tient, il y a
boost::format. Il y a même une classe équivalente à mon site,
dans le répertoire Old/Text. (Je ne la maintient plus, parce que
je n'en vois pas l'utilité.)

--
James Kanze (Gabi Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Sylvain
James Kanze wrote on 24/11/2006 21:44:

évidemment c'est un feature de dubug, donc tu sais que les chaines
formattées ne dépassent jamais la longueur réservée (2048 ici)...


Jusqu'elles le font.


pardon ?

Pourquoi 2048, d'ailleurs ? Pourquoi pas
2000 ? Ou 10000 ?


parce que j'ai dit "je choisis arbitrairement 2048!!!"

De l'autre côté, il y a toujours le problème des types qui ne
conviennent pas.


s'il n'y avait qu'un vague problème de type lorque l'on a besoin de
faire de sortie vers la "console systeme" tout irait bien!!!

la question n'est pas ici, est-ce que je suis capable d'écrire
toto("%d %s", 32, "heelo world")
ou au contraire suffisemment con pour mettre
toto("%d %s %i %c %f", "hello world", 25, "bouf", "pan")
mais juste de tracer (par exemple) si l'on rentre ou non dans une
fonction qui ne peut pas être tracée sous debugger symbolique.

Printf et compagnie, c'est un core dump larvé.


lorsque l'on fait exprès d'être bête, oui.

Comme Loïc, je ne trouve pas la syntaxe de printf
particulièrement conviviable. Mais si on y tient, il y a
boost::format.


bien sur il y a toujours des centaines de kilos de librairie pour
remplacer une primitive inutilement (dans le contexte) du CRT, ...

Il y a même une classe équivalente à mon site,
dans le répertoire Old/Text. (Je ne la maintient plus,
parce que je n'en vois pas l'utilité.)


?! moi non plus je ne verrais pas l'utilité d'une usine à gaz pour
logger des "in toto, leaving titi".

Sylvain.


Avatar
Loïc Joly

la question n'est pas ici, est-ce que je suis capable d'écrire
toto("%d %s", 32, "heelo world")
ou au contraire suffisemment con pour mettre
toto("%d %s %i %c %f", "hello world", 25, "bouf", "pan")
mais juste de tracer (par exemple) si l'on rentre ou non dans une
fonction qui ne peut pas être tracée sous debugger symbolique.


J'ai déjà vu des bugs dans du code de log écrit à la printf. Ils sont
d'autant plus difficiles à trouver qu'on a tendance à sauter ce code à
la relecture.

?! moi non plus je ne verrais pas l'utilité d'une usine à gaz pour
logger des "in toto, leaving titi".


En général, ce que j'aime logger ressemble plus à :
"Itération 3 : Objet = {1, 3, "Toto", true}"
Et que j'aime écrire :

log << "Iteration " << i << " : Object = " << object;

Je ne sais pas écrire la même chose simplement avec printf.

--
Loïc

Avatar
Sylvain
Loïc Joly wrote on 24/11/2006 23:14:

J'ai déjà vu des bugs dans du code de log écrit à la printf.


je l'ai dit, on a le droit d'être nul, stupide, incompétent, ...
moi aussi, j'ai jamais (trop souvent) vu du code pourri du début à la
dernière ligne - les artifices de librairie top-fashion n'y changaient rien.

Ils sont d'autant plus difficiles à trouver qu'on a tendance à sauter
ce code à la relecture.


oui, les mauvais développeurs n'écrivent généralement pas de tests
unitaires et s'ils le font - pour reprendre ton point - ils ne
qualifient surtout pas ces procédures de tests.

alors la plupart se rassure à coup de std::machin ou boost::truc...

En général, ce que j'aime logger ressemble plus à :
"Itération 3 : Objet = {1, 3, "Toto", true}"
Et que j'aime écrire :
log << "Iteration " << i << " : Object = " << object;

Je ne sais pas écrire la même chose simplement avec printf.


*tu* ne sais pas, et alors ?
d'autre sauront écrire
printf("Iteration %d : Object = %s", i, object.toString());
(en essayant de donner un sens à "log << object" qui ne peut rien dire à
sa seule lecture (obfuscation ici non décriée)).

Sylvain.

Avatar
David F.
En aparté,

Loïc Joly wrote on 24/11/2006 23:14:
[...]


oui, les mauvais développeurs n'écrivent généralement pas de tests
unitaires et s'ils le font - pour reprendre ton point - ils ne
qualifient surtout pas ces procédures de tests.

alors la plupart se rassure à coup de std::machin ou boost::truc...


Un peu dur comme propos même si je serai plutôt d'accord sur le fond.

[...]

*tu* ne sais pas, et alors ?
d'autre sauront écrire
printf("Iteration %d : Object = %s", i, object.toString());


Pour printf, object::toString() semble non trivial pour être à la fois
sans fuite et surtout "thread safe". Enfin, en tout cas, je ne vois pas
de trop comment la faire simple.

David


[...]

Avatar
Sylvain
David F. wrote on 25/11/2006 00:10:
En aparté,


en effet - voire HS, la ""bonne critique"" à ce post aurait été un
renvoi sur fr.comp.os.ms-win[].prog[], pas vraiment sur l'art de se
planter dans un printf.

Un peu dur comme propos même si je serai plutôt d'accord sur le fond.


je trouve aussi assez dur, les raccourcis qui consistent à prétendre que
tel ou tel façon de faire ou telle fonction est intrinsèquement hors de
portée et qu'il n'y a pas d'autres choix que d'utiliser tel wrapper.

soit, toute méthode a ses limites et contraintes, et on peut les
rappeler au moment opportun, mais refuser par prinicipe tient plus du
fait de prendre le codeur pour un crétin qui ne saura pas évoluer dans
ces limites; lui conseiller boost::truc qui lui est codé intelligemment
(contrairement aux productions du demandeur) est "un peu dur".

Pour printf, object::toString() semble non trivial pour être à la fois
sans fuite et surtout "thread safe". Enfin, en tout cas, je ne vois pas
de trop comment la faire simple.


la problématique, d'accès concurrentiel notamment, sera (quasiment)
exactement la même pour coder le ostream& << (ostream&, Object&);
(quasiment car le problème de la chaine retournée n'existe que pour
l'appel à une fonction).

Sylvain.

Avatar
David

Pour printf, object::toString() semble non trivial pour être à la fois
sans fuite et surtout "thread safe". Enfin, en tout cas, je ne vois pas
de trop comment la faire simple.


la problématique, d'accès concurrentiel notamment, sera (quasiment)
exactement la même pour coder le ostream& << (ostream&, Object&);
(quasiment car le problème de la chaine retournée n'existe que pour
l'appel à une fonction).


A 1h00 du matin et rapidement, je n'ai pas trouvé les mêmes problèmes
dans ces deux approches.

J'imaginais quelque chose comme ça pour toString() :
const char* object::toString() const {
...
return quelquechose;
}

et là je ne vois pas trop de solution simple notamment pour la
concurence sur un hypothétique buffer static (un peu à la "C" je dirais)


alors qu'avec un
std::string object::toString() const {
// ou asString(), j'hésite toujours.
string tmp;
// ...
return tmp;
}

puis, pour faciliter une utilisation en mode flux :
ostream& operator << ( ostream& os, const object& o ) {
return os << o.toString();
}

mes connaissances ne me permettent pas de détecter de vrai problème.

David.


1 2 3 4 5