J'essaie de me débarrasser de certains avertissements du compilateur disant que strcpy, sprintf, etc ne sont pas sûrs… .. Je comprends pourquoi ils sont dangereux, mais je ne trouve pas de bonne façon de corriger le code en C++. style.
Voici un extrait du code:
extList->names[i]=(char *)malloc(length*sizeof(char));
strcpy(extList->names[i],extName); // unsafe
// strncpy(extList->names[i],extName,length); // also unsafe
Voici le message:
C4996: 'strcpy': cette fonction ou variable peut être peu sûr. Pensez à utiliser strcpy_s à la place. Pour désactiver la désapprobation, utilisez _CRT_SECURE_NO_WARNINGS. Voir l'aide en ligne pour plus de détails.
Je ne peux pas penser à un moyen sûr de copier les données en C++ sans connaître la longueur de l'élément à copier .. Je sais qu'il existe strlen (), mais c'est aussi dangereux car cela suppose (peut-être à tort) que les données est terminé par un zéro.
Également:
// used to concatenate:
sprintf(extStr,"%s%s",platExtStr,glExtStr);
C4996: 'sprintf': Cette fonction ou cette variable peut être dangereuse. Considérer en utilisant sprintf_s à la place. Pour désactiver la désapprobation, utilisez _CRT_SECURE_NO_WARNINGS. Voir l'aide en ligne pour plus de détails.
Utiliser std :: string pour concaténer est assez facile, mais je dois ensuite obtenir les données dans extStr d'une manière ou d'une autre (sans utiliser strcpy, lol). La fonction string :: c_str () renvoie un pointeur sur des données non modifiables, je ne peux donc pas simplement lui donner extStr égal. (Et je ne suis même pas sûr si le pointeur c_str () doit être supprimé ultérieurement appelé. Est-ce qu'il alloue de l'espace en utilisant "nouveau"?)
Vous avez des conseils à ce sujet? Cela fait partie d'un fichier de 10 000 lignes qui n'est pas le mien ... je ne suis donc pas particulièrement intéressé par la réécriture de la chose en C++.
Vous n'avez pas vraiment besoin de pragmas pour les désactiver.
Pour win32/msvc, dans ProjectProperties -> Propriétés de configuration -> C/C++ -> Préprocesseur -> Définitions du préprocesseur, ajoutez les macros suivantes:
_CRT_SECURE_NO_DEPRECATE
_CRT_NONSTDC_NO_DEPRECATE
Vous pouvez également transmettre ces paramètres dans les paramètres de ligne de commande (-D_CRT_SECURE_NO_DEPRECATE). Vous pouvez probablement les définir au début de certains fichiers * .cpp. En outre, il y en a probablement plus (voir crtdefs.h - on dirait qu'il y en a beaucoup ...). Ce type d’avertissements vous indique normalement avec quelles macros vous pouvez les désactiver - il suffit de lire les résultats du compilateur.
Voici une autre réponse à cette question.
#ifdef _MSC_VER
#pragma warning(Push)
#pragma warning(disable : 4996)
#endif
strcpy(destination, source);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Si votre objectif est uniquement de vous débarrasser des avertissements ... définissez simplement ce _CRT_SECURE_NO_WARNINGS
et il supprimera tous les avertissements de dépréciation. Mais cela ne résoudra pas les problèmes sous-jacents liés aux fonctions CRT non sécurisées.
Si vous utilisez la version de Visual Studio> = 2005 et que vous souhaitez corriger ces avertissements de manière appropriée, la méthode la plus simple consiste à #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
et #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
dans votre projet.
sans autre changement de code, vous pouvez observer que la plupart des avertissements sont corrigés automatiquement. En définissant cette fenêtre, les fonctions sécurisées surchargées seront automatiquement appelées pour la plupart des fonctions CRT dangereuses. Les tailles de tampon pour les tableaux statiques sont calculées automatiquement.
Bien que les tampons alloués dynamiquement ne soient pas corrigés de cette manière, nous devons les corriger manuellement. S'il vous plaît se référer ce lien pour plus de détails.
Vous trouverez ci-dessous une façon de corriger votre exemple par programmation.
strcpy_s(extList->names[i], length, extName);
Vous savez combien de copies vous avez alloué un espace!
Vous ne voudriez sûrement pas copier plus que l’espace alloué?
Je préférerais utiliser une méthode qui évite explicitement les dépassements de mémoire tampon en limitant le nombre d'éléments copiés. À l'époque où j'étais programmeur C, nous utilisions
dest = malloc(len); // note: where did we get len?
if ( dest is null ) panic! // note: malloc can fail
strncpy(dest, src, len);
dest[len-1] =0;
Ceci est légèrement désordonné, et a été souligné l'utilisation de strncpy (), une méthode qui avait été initialement conçue pour les champs de largeur fixe plutôt que les chaînes. Cependant, il fait mal
Il existe des méthodes telles que strdup () et strlcpy () que nous pouvons aider.
Mes recommandations:
1). Votre cible ne doit pas être de supprimer les avertissements mais de rendre le code robuste.
2) Lors de la copie de chaînes, vous devez vous assurer que:
Si strlcpy () est disponible dans votre environnement, vous pouvez l'utiliser, sinon pourquoi ne pas écrire votre propre petite fonction utilitaire? Ensuite, s'il y a des avertissements dans cette fonction, vous avez localisé le problème.
Dans votre premier exemple, vous connaissez déjà la longueur. Puisque vous n'allouez pas length+1
octets, je supposerai que length
INCLUS le terminateur nul. Dans ce cas, il suffit de std::copy
la chaîne: std::copy(extName, extName + length, expList->names[i]);
Dans votre deuxième exemple, en supposant que les chaînes source sont terminées par un caractère nul, vous pouvez calculer la longueur de la chaîne de destination et utiliser à nouveau std::copy
pour concaténer manuellement. Vous pouvez également utiliser std::string
et le std::copy
des résultats de c_str
dans votre destination il).
c_str()
n'alloue pas de mémoire qui nécessiterait une suppression externe.
Enfin, notez que sizeof(char)
sera toujours un et qu’il est donc redondant dans votre malloc, bien que le nombre de bits de ce caractère ne soit pas nécessairement égal à 8 (voir CHAR_BIT
).
Je pense que vous devriez remplacer tous les appels de fonction si possible appeler votre propre implémentation. Un bon exemple ici serait une fonction permettant de remplacer strcpy et d’appeler la version de strcpy spécifique au compilateur. Votre implémentation peut ensuite être facilement modifiée pour correspondre au compilateur de votre choix, en particulier si vous souhaitez ajouter ou modifier des plates-formes/compilateurs.
Exemple:
char* StringCopy(char* Destination, const char* Source, size_t DestinationSize)
{
#ifdef _MSC_VER
return strcpy_s(Destination, Source, DestinationSize);
#else
if(!(strlen(Source) >= DestinationSize))
return strcpy(Destination, Source);
else
return 0x0;
#endif
}
Si la portabilité n'est pas un problème, vous pouvez utiliser 'strcpy_s' .
Si ce code ne doit être compilé que pour la plate-forme Windows, il est préférable d'utiliser la version sécurisée de ces fonctions. Toutefois, si ce code doit être compilé sur plusieurs plates-formes (Linux, Aix, etc.), vous pouvez désactiver l'avertissement dans le fichier de configuration de votre projet Windows (par exemple, .vcxproj) à l'aide de _CRT_SECURE_NO_WARNINGS ou utilisez un extrait de code, celui-ci à des endroits où ces fonctions ont été appelées dans le fichier .cpp.
#if _OS_ == _OS__WINDOWS
//secure function call
#else
//already written code
#endif
comme suggéré dans le message, utilisez _CRT_SECURE_NO_WARNINGS pour désactiver ces avertissements.
dans ProjectProperties -> Propriétés de configuration -> C/C++ -> Préprocesseur -> Définitions de préprocesseur, ajoutez les macros suivantes:
_CRT_SECURE_NO_WARNINGS