Qu'est-ce qui se passe est que je lis je lis des paquets de cryptage et je rencontre un paquet corrompu qui redonne un très grand nombre aléatoire pour la longueur.
#include "stdafx.h" #include <vector> #include <iostream> #include <math.h> #include <typeinfo> typedef std::vector<unsigned char> vector_unsigned_char; void fill(vector_unsigned_char& v) { for (int i=0; i<100; i++) v.push_back(i); } void oput(vector_unsigned_char& v) { std::cout << "size: " << v.size() << std::endl; std::cout << "capacity: " << v.capacity() << std::endl; std::cout << "max_size: " << v.max_size() << std::endl << std::endl; } void main(int argc, char* argv[]) { { vector_unsigned_char v; fill(v); try{ v.resize(static_cast<size_t>(3555555555)); }catch(std::bad_alloc&) { std::cout << "caught bad alloc exception" << std::endl; }catch(const std::exception& x) { std::cerr << typeid(x).name() << std::endl; }catch(...) { std::cerr << "unknown exception" << std::endl; } oput(v); v.reserve(500); oput(v); v.resize(500); oput(v); } std::cout << "done" << std::endl; }
3 Réponses :
Je pense que 'Bug' pourrait être trop fort d'un mot. Si une exception est lancée autrement que par le constructeur de copie ou l'opérateur d'affectation de T, il n'y a aucun effet p>
blockQuote>
Il semble donc qu'il peut y avoir des moments où le fonctionnement code> () code> est autorisé à corrompre un vecteur, mais il serait toujours sympa si l'opération était en sécurité (et je pense que cela ne serait pas T Soyez hors de ligne pour vous attendre à ce que la bibliothèque fasse cela, mais peut-être qu'il est plus difficile que j'imagine). P>
Vous semblez avoir quelques options raisonnables: p>
EDIT: P>
Je vois que vous utilisez VC6 - il y a définitivement un bug dans Le problème peut également avoir quelque chose à voir avec le correctif Notez que Scott Meyers dans "Efficace STL" suggère d'utiliser SGI's ou < Un href = "http://www.stlport.org/" rel = "noreferrer"> la bibliothèque de STLORT pour obtenir un meilleur support STL que par VC6. Je n'ai pas fait ça, donc je ne suis pas sûr à quel point ces bibliothèques fonctionnent (mais je n'ai pas aussi utilisé VC6 avec beaucoup de stl). Bien sûr, si vous avez la possibilité de passer à une version plus récente de VC, faites-le. P>
une autre modification: p>
Merci pour le programme de test ... P>
de sorte que la fin de la ligne ne soit jamais demandée à VC6 d'allouer plus de En outre, vous devez garder à l'esprit que VC6 utilise un idiome pré-standard de retour 0 à partir de vecteur :: max_size () code> est toujours toujours une chose «codée dur» - il est indépendant de la quantité de mémoire que le système / la bibliothèque est préparé pour allouer de manière dynamique. Votre problème semble être un bogue dans la mise en œuvre du vecteur qui corrompt les choses lorsqu'une attribution échoue. P>
Vecteur :: redimension () code> est défini en termes de
Vector :: Insérer () code> et la norme indique ceci sur
vecteur :: insert () code> : p>
vector :: max_size () code> définir
nmaxsize code> à votre propre maximum raisonnable et faites ce que vous avez ci-dessus mais en utilisant ce seuil à la place. LI>
ul>
vecteur :: redize () code> qui pourrait avoir quelque chose à voir avec votre problème, mais en regardant le patch, je ne fais pas Voyez comment (en fait c'est un bogue dans
vecteur :: insérer () code>, mais comme mentionné,
redimensionne () code> appels
insérer () code>). J'imaginerais qu'il serait intéressant de visiter page de dinkumwares pour les corrections de bugs à VC6 et appliquer le Corrections. p>
vecteur :: insérer () Code> Est-ce que Call
_Destroy () code> et
vecteur <> code> définit le nom
_ty code> afin que vous puissiez suivre ce problème. Une bonne chose - vous n'aurez pas à vous soucier de gérer les modifications apportées aux en-têtes, car Microsoft ne les touche jamais. Assurez-vous simplement que les patchs en font le contrôle de la version et sont documentés. P>
_Alloquer () code> implémentation pour l'allocator par défaut (dans
_Allocate () code> fonctionne la taille de l'allocation demandée à zéro et au produit. Notez qu'une demande d'allocation de taille zéro va toujours toujours réussir (pas que
vecteur code> vérifie quand même une panne), donc le vecteur
vecteur :: redize () code> fonction joyeusement essaie de Déplacez son contenu dans le nouveau bloc, ce qui n'est pas assez grand pour le moins important. Donc, le tas est corrompu, il va probablement toucher une page de mémoire invalide, et quel que soit votre programme. P>
int_max code> d'objets en une fois. Probablement pas une bonne idée dans la plupart des circonstances (VC6 ou autre). P>
Nouveau code> lorsqu'une allocation échoue plutôt que de lancer
Bad_alloc code>. P>.
"Si une exception est lancée autrement que par le constructeur de copie ou l'opérateur d'affectation de T, il n'y a pas d'effets" IRTA ", c'est comme si redimensionne () code> n'a pas été appelé." Et je suis assez sûr que aucune opération sur un vecteur n'est censée corrompue la mémoire.
L'opération Insérer () peut entraîner des opérations de copie / d'affectation (lorsque le contenu du vecteur est copié dans une nouvelle allocation) - ceux-ci sont autorisés à «avoir un effet». Cela ne devrait rien faire aussi mal que de corrompre le tas par exemple, mais il n'est pas clair si c'est ce qui se passe à l'OP. Une exception sous ces conditions est autorisée à donner un vecteur changé (peut-être que tous les éléments du vecteur ne se rendent pas au nouveau). Son code peut constater que le vecteur n'a plus de sens. De toute façon, n'est pas un grand comportement et je conviens qu'une implémentation stl pourrait mieux gérer la situation.
Vous avez raison, cependant que la copie / l'attribution d'éléments dans un vecteur
"Une exception dans ces conditions est autorisée à donner lieu à un vecteur changé" si tel est vrai, je serais surpris. En outre, je ne vois pas comment lire ceci de ce que vous avez cité.
La façon dont je lis cette ligne dans la norme est que si une exception est lancée dans un Vecteur :: insert () code> appel alors que rien ne sera arrivé au vecteur ("pas d'effets") à moins que l'exception ne soit arrivée À partir d'une copie CTOR ou d'un opérateur d'affectation, auquel cas on pourrait avoir eu un effet (non spécifié). Là encore, les documents de normalisation ne sont pas connus pour la clarté de cristal. Je pourrais donc être hors de base.
@Michael: À la lecture de la ré-lecture, je suis d'accord avec vos doutes.
Je suggère fortement que vous vérifiez vos données pour les corruptions avant d'appeler des fonctions de bibliothèque avec des arguments erronés! strong> p>
Utilisez une sorte de code de hachage ou cochez la somme algorithme de somme sur vos paquets.
Vous ne pouvez pas compter sur la bibliothèque pour vous aider puisqu'il ne peut pas faire:
Il se peut que vous lui donniez un corrompu mais toujours valide (du point de vue de la bibliothèque) la taille réelle qui est réelle afin d'allouer par exemple 768 Mo de RAM. Cela peut fonctionner s'il y a suffisamment de mémoire libre dans le système mais peut échouer s'il existe d'autres programmes qui consomment trop de mémoire sur votre machine de 1024 Mo. P>
Ainsi, comme indiqué ci-dessus: Vérifiez d'abord! P>
Je suis d'accord. Je pense que la racine de votre problème est que vous comptez sur votre algorithme de cryptage pour vous indiquer la taille "prétend" être. Vous avez vraiment besoin d'une application de taille de bloc avec un rembourrage (comme MD5 le fait) ou d'avoir un autre moyen hors bande de fournir des informations sur la taille.
Je suis d'accord, nous avons besoin d'une méthode pour valider les paquets. Je vais mentionner cela aux autres programmeurs de ce projet lundi. Pour l'instant, je vais juste sauter le paquet s'il est plus grand que 5 Mo.
Je n'ai aucune idée de ce que vous voulez dire lorsque vous dites "Redimentation a une mémoire corrompue". Comment déterminez-vous cela?
FWIW, je ne suis pas d'accord avec La réponse de Michael . Si avec Peu importe ce qu'il est, il devrait être dérivé de Quoi qu'il en soit, quoi que ce soit, je suis assez sûr de ne pas corrompre la mémoire. Soit c'est un bogue dans votre mise en œuvre STD lib liber (improbable, si vous me demandez, sauf si vous utilisez un très ancien) ou que vous avez fait quelque chose de mal ailleurs. p> edit fort> Maintenant que vous avez dit que vous utilisez VS6 ... P> Vous auriez dû dire cela plus tôt. VC6 a été publié il y a plus d'une décennie, après que MS avait perdu leur vote dans le comité STD, car ils n'avaient pas comparu à des réunions depuis trop longtemps. La mise en œuvre de STD LIB qu'ils avaient expédiées provenaient de Dinkumware (Good), mais en raison du problème juridique, c'était celui pour VC5 (très mauvais), qui avait beaucoup de bugs plus petits et plus importants et n'avait même pas de soutien aux modèles membres, même si Le compilateur VC6 a soutenu. Honnêtement, qu'attendez-vous d'un tel produit? p> Si vous ne pouvez pas passer à une version VC décente (je recommanderais au moins VC7.1 aka vs.net 2003, comme c'était celui qui a fait le saut majeur vers la conformité standard), au moins voir si Dinkumware Vendez toujours une version VC6T de leur excellente bibliothèque. (En fait, je serais surpris, mais ils avaient l'habitude d'en avoir un et vous ne savez jamais ...) p> comme pour les exceptions: dans la version VC antérieure (ceci inclut VC6 et n'inclut pas VC8 AKA VS .NET 2005, je ne suis pas sûr de VC7.1, cependant) par défaut des violations d'accès pourraient être capturées par std :: vecteur <> :: redimensionnement () code> jette sur l'expansion de vecteur, je vois deux possibilités: p>
std :: vecteur
std :: allocator code> doit être utilisé et, Afaik, qui appellera
nouveau code> pour allouer la mémoire. Et
nouveau code> lancerait
std :: bad_alloc code>. Cependant, vous dites que vous ne pouvez pas attraper cela, alors je ne sais pas ce qui se passe. P>
std :: exception code>, afin que vous puissiez le faire pour savoir: p>
Catch (...) Code>. Donc, si un tel bloc de captures a attrapé quelque chose, vous ne sauriez pas si cela était une exception C ++. Mon conseil serait de ne utiliser que
attraper (...) code> dans la conférence avec
lancer; code> afin de laisser cette exception passer. Si vous le faites, vous obtenez un véritable accident chez AV et êtes capable de les tracer dans le débogueur. Si vous ne le faites pas, AV sera avalé et vous êtes coincé avec une application qui est partie Berserk sans que vous sachiez même. Mais faire quelque chose mais abandonner avec une application AV'ed n'a aucun sens. Un AV est un résultat de comportement non défini em> et après cela, tous les paris sont éteints. P> p>
La raison pour laquelle je dis que cela corrompue la mémoire est parce que des déclarations de journal simples commencent à lancer des exceptions et que tout un tas d'affirmations liées à la mémoire continue de se lever. Après la fonction de redimensionnement, tout le programme perd l'esprit. Cela n'arrive pas si vous réussissez à redimensionner une longueur raisonnable. Cela n'arrive pas si je saute ce paquet non plus. Je vais essayer ce code pour déterminer le type d'exception, je ne savais pas sur Typeid! Merci.
Si vous ne saviez pas: vous devez #include
Croyez-le ou non, le const Std :: Exception et Handler ne l'ont pas attrapé. Je n'indique aucune idée de cette exception. Maintenant, je commence vraiment à croire que la version de la STL que nous utilisons a un bogue dedans. Je discuterai de cela avec le programmeur mène lundi.
Pour attraper avec succès une violation d'accès (AKA SEH Exception), vous devez définir le réglage du compilateur / EHA. @cchampion: Cela expliquerait pourquoi vous n'attribuez pas l'exception, car ce n'est probablement pas une exception C ++
Je suis curieux de savoir quelle version compilateur / stl utilisez-vous. Les implémentations que j'ai accès ne corrompre pas l'objet vectoriel si l'allocation a échoué.
@cchampion: "Sur ma machine de développement VS6 ..." Vous l'avez dit plus tôt, nous n'aurions pas perdu autant de temps à ce sujet. C'est plus de 10 ans de technologie! Bien sûr, c'est buggy. Voir ma réponse.
Consultez mes modifications plus récentes - Le problème est un bug dans le code> code> (mais pas celui qui a été discuté sur la page Dunkumway VC Bugs).