2010-02-24 12 views
5

Nous avons une application C++/MFC qui permet aux utilisateurs de personnaliser la mise en forme de la date via des fichiers de configuration. Ne voulant pas réinventer la roue, je passe la chaîne de format à CTime :: Format ("< chaîne de format>") pour faire le formatage réel. Sous les couvertures, Format appelle une variante de la fonction C standard strftime().Appel sécurisé de strftime avec une chaîne de format non fiable

Naturellement, l'utilisateur peut entrer accidentellement une chaîne de format invalide. (Par exemple, "% s" au lieu de "% S".) Lorsque cela se produit, C Run-Time appelle le Invalid Argument Handler qui, par défaut, quitte l'application. (Aucune exception à attraper - juste une sortie d'application.)

Ma question est comment gérer avec élégance cette entrée non fiable. En théorie, je pouvais écrire mon propre analyseur/validateur pour la chaîne de format, mais cela ressemblait à une perte de temps. Au lieu de cela, le mieux que je pouvais trouver était de mettre mon propre (global) gestionnaire d'argument non valide qui, au lieu de sortir, renvoie une exception Argument non valide:

void MyInvalidParameterHandler(
    const wchar_t* expression, 
    const wchar_t* function, 
    const wchar_t* file, 
    unsigned int line, 
    uintptr_t pReserved) 
{ 
    ::AfxThrowInvalidArgException(); 
} 

Cela ne semble pas fonctionner, et permet à mon explicitement attraper (et gérer gracieusement) les exceptions d'arguments invalides dans les cas où je "m'attends" à ce qu'elles se produisent. Cependant, je suis préoccupé par le fait que je remplace un paramètre global d'exécution dans une grande application afin de résoudre un problème relativement «local» - Je détesterais que cette correction provoque des problèmes supplémentaires ailleurs.

Cette approche est-elle sensée? Ou y a-t-il une approche plus propre pour résoudre ce problème?

Répondre

3

Si vous ne souhaitez intercepter cette erreur qu'à certains moments, vous pouvez remplacer temporairement le gestionnaire de paramètres non valide, puis le rétablir après avoir appelé Format.

_invalid_parameter_handler oldHandler = _set_invalid_parameter_handler(MyInvalidParameterHandler); 

// Your try/Format/catch code here 

_set_invalid_parameter_handler(oldHandler); 

Bien sûr, je suppose qu'il est possible que si vous avez plusieurs threads dans votre programme, un autre thread pourrait finir par appeler votre gestionnaire de paramètre non valide alors qu'il est défini. Vous devriez déterminer la probabilité de cela.

En plus d'écrire votre propre fonction de validation, je ne sais pas comment vous pourriez faire autrement.

+0

Nous vous remercions de votre suggestion. Malheureusement, mon application est en fait multi-threadée, donc je ne pense pas que je peux basculer en toute sécurité le gestionnaire d'avant en arrière. (Le gestionnaire de paramètre invalide est global, plutôt que spécifique au thread.) –

+0

Dans ce cas, je crois que vous devrez créer votre propre fonction de validation. Ça ne devrait pas être si difficile. Si vous regardez dans strftime.c dans le code source CRT, vous verrez une fonction appelée _expandtime. Il contient une instruction case pour tous les spécificateurs de format pris en charge. Vous pouvez l'utiliser comme base pour votre fonction. – Dustin

+0

Une possibilité consiste à ajouter votre propre gestionnaire de paramètres invalide qui ne fait rien. Les docs indiquent que si le contrôle retourne à la fonction appelante, il retournera un code d'erreur. – Dustin