Qu'est ce que “mal Alignées erreur d'adresse”?
Tout d'abord, désolé pour les détails. De manière générale, j'essaie de faire bouillir mes questions génériques de "classe A" des choses avec seulement pertinente des trucs, mais je ne suis pas sûr de ce qui est la source du problème ici.
J'ai une matrice de modèle de classe qui ressemble à ceci (seulement montrer ce que je pense sont les parties pertinentes):
template <std::size_t R, std::size_t C>
class Matrix
{
private:
//const int rows, cols;
std::array<std::array<float,C>,R> m;
public:
inline std::array<float,C>& operator[](const int i)
{
return m[i];
}
const std::array<float,C> operator[](const int i) const
{
return m[i];
}
template<std::size_t N>
Matrix<R,N> operator *(const Matrix<C,N> a) const
{
Matrix<R,N> result = Matrix<R,N>();
//irrelevant calculation
return result;
}
//... other very similar stuff, I'm not sure that it's relevant
}
template <std::size_t S>
Matrix<S,S> identity()
{
Matrix<S,S> matrix = Matrix<S,S>();
for(std::size_t x = 0; x < S; x++)
{
for(std::size_t y = 0; y < S; y++)
{
if (x == y)
{
matrix[x][y] = 1.f;
}
}
}
return matrix;
}
J'ai testé unitaire de l'ensemble de la classe, à la fois la multiplication et de l'identité de l'usine semble fonctionner très bien. Cependant, puis-je utiliser cette méthode, qui est appelée à beaucoup de fois (je pense que si vous avez déjà écrit-un moteur de rendu, c'est assez évident ce que je suis en train de faire ici):
Vec3i Renderer::world_to_screen_space(Vec3f v)
{
Matrix<4,1> vm = v2m(v);
Matrix<4,4> projection = identity<4>(); //If I change this to Matrix<4,4>(), the error doesn't happen
projection[3][2] = -1.f;
vm = projection * vm;
Vec3f r = m2v(vm);
return Vec3i(
(r.x + 1.) * (width / 2.),
(r.y + 1.) * (height / 2.),
r.z
);
}
Et après un certain laps de temps et une certaine quantité de hasard les appels à cette méthode, j'obtiens ceci:
Job 1, 'and ./bin/main' terminated by signal SIGBUS (Misaligned address error)
Cependant, si je change la ligne identity<4>()
à Matrix<4,4>()
l'erreur ne se produise pas. Je suis novice en C++, donc ça doit être quelque chose de vraiment stupide.
Donc, (1) que signifie cette erreur moyenne et (2) comment j'ai réussi à me tirer une balle dans la jambe?
Mise à jour: et bien sûr, ce bug ne sera pas reproduire dans la LLDB débogueur.
Mise à jour 2: voici ce que j'ai obtenu après l'exécution du programme par le biais de Valgrind:
==66525== Invalid read of size 4
==66525== at 0x1000148D5: Renderer::draw_triangle(Vec3<float>, Vec3<float>, Vec3<float>, Vec2<int>, Vec2<int>, Vec2<int>, Model, float) (in ./bin/main)
Et draw_triangle
est exactement la méthode qui appelle world_to_screen_space
et l'utilise.
Mise à jour 3: j'ai découvert la source du problème, et ce n'était pas quelque chose lié à ce code — et c'était quelque chose d'assez évident, trop. Vraiment ne savez pas quoi faire à propos de cette question maintenant.
Si il arrive encore (sans un débogueur), permettent core dumps, puis inspectez le dump avec un débogueur.
Je n'utilise pas les pointeurs dans le code, seules les références ou la copie par valeur.
Le problème est probablement dans votre
operator[]
mise en œuvrePlus courte et plus simple le code est aussi plus facile de se corriger.
OriginalL'auteur Max Yankov | 2015-02-25
Vous devez vous connecter pour publier un commentaire.
Sans un processeur qui vérifie les erreurs d'alignement (comme @twalberg dit), il est impossible d'exécuter et valider le code. Mais je peux dire ceci: c'est un bug dans le C++ ou d'autres bibliothèques pour confondre un type d'exception avec un autre type.
Je pense-désolé, je ne peux pas faire plus, c'est que vous êtes la création d'allocations qui se perdent, à l'aide de votre mémoire disponible, puis débordant l'espace de la mémoire. La très rare exception levée lorsque vous dépassez la mémoire disponible est probablement inattendu et se retourna comme un désalignement de l'erreur. Essayez de vérifier l'utilisation de la mémoire lorsque vous exécutez, afin de déterminer si cela pourrait être le cas.
EDIT:
Ma supposition était fausse, et la valgrind sortie montre que le mal aligné d'erreur d'adresse était correcte. La course, qui était une bonne idée. L'indication claire qu'il y a un bug à un niveau plus bas que dans votre code, donc mon idée de départ est presque certainement correct: il y a un bug qu'il n'est pas dans votre code, mais il est masqué.
Noter qu'il semble y avoir une différence entre l'identité() constructeur et la Matrice<,> constructeur en ce que la première est initialisé le long de la diagonale (lentement: le mieux serait de supprimer la boucle interne) et le second ne l'est pas. Qui peuvent affecter le comportement de v2m et m2v.
Je n'en ai pas; mais pas tout le code a été montré. Je suis d'édition ma réponse maintenant, basé sur l'entrée de valgrind.
J'ai découvert le problème, et il s'avère qu'elle n'avait rien à voir avec le code que j'ai posté, et qu'il était vraiment évident. Selon thisje devrais supprimer cette question, mais il y a beaucoup de discussion ici. Pas vraiment sûre de savoir quoi faire avec elle; ne peut pas accepter cette réponse, parce que ce n'est techniquement pas correct (il n'était pas le problème), mais il m'a beaucoup aidé.
Je ne peux pas l'obliger à vous, mais s'il vous plaît noter que comment SE devrait fonctionner dans ce cas. Veuillez lire. Vous pouvez toujours signaler vos notes dans votre réponse.
Merci pour cette discussion, je pense que je vais faire un write-up sur ce problème plus tard aujourd'hui.
OriginalL'auteur shipr