2009-01-11 10 views
4

J'ai rencontré un bug vraiment étrange, que j'espère que quelqu'un peut expliquer. Je simple std::vector<V3x>, où V3x est un vecteur 3d Le code suivant provoque une exception std::length_error à être jeté (le genre d'algèbre linéaire.):Les changements de valeur du paramètre C++ entre les trames de pile dans std :: vector

std::vector<V3x> vertices; 
int vertexCount = computeVertexCount(); 
vertices.resize(vertexCount); // throws std::length_error 

J'ai vérifié que computeVertexCount() retourne une valeur de 35, qui est très loin en dessous de vector::max_size() donc il n'y a aucun moyen de demander trop de mémoire.

J'ai tracé l'exception dans la définition de std::vector, aux deux fonctions suivantes.

void resize(size_type _Newsize, _Ty _Val) 
    { // determine new length, padding with _Val elements as needed 
    if (size() < _Newsize) 
     // NOTE: here, _Newsize - size() = 35 
     _Insert_n(end(), _Newsize - size(), _Val); 
    else if (_Newsize < size()) 
     erase(begin() + _Newsize, end()); 
    } 

void _Insert_n(const_iterator _Where, 
    size_type _Count, const _Ty& _Val) 
    { // insert _Count * _Val at _Where 
     // NOTE: here, _Count = 3435973836 
     ... 
    } 

Ainsi, lorsque le paramètre _Count est passé entre resize() et _Insert_n(), les changements de valeur de 35 à 3435973836. Je suppose la mémoire est en quelque sorte devenu corrompu, mais je ne sais pas comment cela pourrait être.

Pour un peu plus de contexte dans le cas où cela fait partie du problème, ce code se trouve dans un plugin .dll que je charge depuis Softimage XSI.

Est-ce que quelqu'un sait ce qui pourrait causer une telle situation?

EDIT: SOLUTION

nobugz, je pourrais vous embrasser.

La taille de std :: vector changeait dans mon fichier .dll, à cause de _HAS_ITERATOR_DEBUGGING dans VS2008. La recherche m'a conduit à someone with the same problem, et il a été fixé en ajoutant ce qui suit au sommet de mon projet:

// fix stack corruption errors caused by VS2008 
#define _HAS_ITERATOR_DEBUGGING 0 
#define _SECURE_SCL 0 
+0

est std :: vecteur sommets; vraiment une variable locale? sinon, il peut très bien ne pas être créé (à cause du fiasco d'initialisation statique) –

+0

Est-ce que vertices.resize (vertexCount); besoin d'un deuxième argument? –

Répondre

20

La valeur 3435973836 est significative. En hexadécimal, c'est 0xcccccccc. C'est la valeur assignée aux variables locales en mode Débogage par le code d'initialisation de la pile. Lorsque vous le voyez en cours de débogage, vous dites "ah, variable non initialisée". Peut-être que cela vous rapproche un peu plus de la solution.

Vous mentionnez DLL. C'est pertinent aussi. Le débogage d'Iterator peut vous causer des problèmes, vous ne pouvez pas mélanger du code qui a été désactivé avec un code qui ne l'est pas. Étant donné que la DLL est probablement compilé sans, essayez #define _HAS_ITERATOR_DEBUGGING 0.

+1

+1: Merci pour certaines informations très utiles! –

+1

Toujours regarder la représentation hexadécimale de très grandes valeurs inattendues. Ils vous disent souvent que vous n'êtes jamais allé dans la terre, comme celui-ci. –

0

le code affiché est correct et vous pouvez supposer que std :: vecteur n'a pas de bugs. répliquer l'exception dans l'environnement le plus pur possible (nouveau projet vide). pourrait-il être quelque chose de stupide like this dans ComputeVertexCount()?

0

Je suggère de revoir les options C++ configurées pour les projets impliqués. Assurez-vous qu'ils partagent tous les mêmes paramètres d'alignement et d'exécution. Est-ce que vous construisez le .DLL impliqué?

2

Chaque fois qu'un paramètre ou une variable locale change de manière inattendue, il y a de fortes chances que cela soit dû à une corruption de la pile. Cela peut se produire lorsque vous utilisez une variable locale non initialisée ou que vous stockez des données au-delà de la mémoire allouée à une chaîne locale ou un tableau.

Une façon simple de débugger:

  1. Chargez votre programme dans un débogueur.
  2. Insère un point d'arrêt à la première ligne de code dans la fonction incriminée.
  3. Exécute le programme jusqu'à ce qu'il atteigne le point d'arrêt.
  4. Définir une surveillance sur la variable qui change de manière inattendue.
  5. Parcourez la fonction jusqu'à ce que la modification inattendue se produise.

La modification se produira lorsque la mémoire non allouée (ou mal affectée) est écrite. La cible de l'écriture est la variable incriminée.

Questions connexes