Вот, делаю небольшой проект на DX11, для передачи в шейдер использую готовую структуру из СДК - XMMATRIX, #include <xnamath.h>... Походу выполнения стала возникать некоторая проблема, свел все к минимуму и сделал тестовый пример чтобы разобраться.. но так и не пойму в чем дело...
Вот тестовый пример:
Суть такая есть класс CTestMatrix, от него наследуется класс CNewTestMatrix, у класса CNewTestMatrix есть единственный член XMMATRIX test;
Так вот при обращении к этому члену в конструкторе класса CNewTestMatrix происходит Unhandled exception at 0x00a61547 in simple_dx11_qt_app.exe: 0xC0000005: Access violation reading location 0x00000000.
Такое чувство что обращение по нулевому указателю, но как такое может быть хз... И такое происходит именно при наследовании, т.е. если юзать этот класс просто так, то все работает нормально.
Код ниже:
Хедер класса test_matrix.h
#ifndef _TEST_MATRIX_H_ #define _TEST_MATRIX_H_ #include <d3d11.h> #include <d3dx11.h> #include <xnamath.h> ////////////////////////////////////////////////////////////////////////// class CTestMatrix { public: CTestMatrix(){}; ~CTestMatrix(){}; }; ////////////////////////////////////////////////////////////////////////// class CNewTestMatrix : public CTestMatrix { public: CNewTestMatrix(); ~CNewTestMatrix(){}; protected: XMMATRIX test; }; ////////////////////////////////////////////////////////////////////////// #endif //_TEST_MATRIX_H_
Цепепшник класса test_matrix.cpp
#include "test_matrix.h" CNewTestMatrix::CNewTestMatrix() { XMMATRIX temp; temp.r[0] = test.r[0]; /// Тут происходит краш : Access violation reading location 0x00000000. }
Майн:
#include "test_matrix.h" int main(int argc, char** argv) { CNewTestMatrix* aaa = new CNewTestMatrix; }
Вот смущает немного сам класс матрицы, что перед ним стоит какоето выравнивание по 16бит, причем первый дефайн не проходит и срабатывает именно то описание структуры которое с выравниванием
Класс матрицы:
// Matrix type: Sixteen 32 bit floating point components aligned on a // 16 byte boundary and mapped to four hardware vector registers #if (defined(_XM_X86_) || defined(_XM_X64_)) && defined(_XM_NO_INTRINSICS_) typedef struct _XMMATRIX #else typedef _DECLSPEC_ALIGN_16_ struct _XMMATRIX // срабатывает это описание , хз че такое _XM_NO_INTRINSICS_ не определяется ............ #endif { union { XMVECTOR r[4]; struct { FLOAT _11, _12, _13, _14; FLOAT _21, _22, _23, _24; FLOAT _31, _32, _33, _34; FLOAT _41, _42, _43, _44; }; FLOAT m[4][4]; }; #ifdef __cplusplus _XMMATRIX() {}; _XMMATRIX(FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3); _XMMATRIX(FLOAT m00, FLOAT m01, FLOAT m02, FLOAT m03, FLOAT m10, FLOAT m11, FLOAT m12, FLOAT m13, FLOAT m20, FLOAT m21, FLOAT m22, FLOAT m23, FLOAT m30, FLOAT m31, FLOAT m32, FLOAT m33); _XMMATRIX(CONST FLOAT *pArray); FLOAT operator() (UINT Row, UINT Column) CONST { return m[Row][Column]; } FLOAT& operator() (UINT Row, UINT Column) { return m[Row][Column]; } _XMMATRIX& operator= (CONST _XMMATRIX& M); #ifndef XM_NO_OPERATOR_OVERLOADS _XMMATRIX& operator*= (CONST _XMMATRIX& M); _XMMATRIX operator* (CONST _XMMATRIX& M) CONST; #endif // !XM_NO_OPERATOR_OVERLOADS #endif // __cplusplus } XMMATRIX;
вообщем падает вроде из за выравнивания, но че делать не пойму пока
попробуй переопределить оператор new/delete как-то так:
#define INL __forceinline INL PVOID __cdecl operator new (size_t sz) { return _aligned_malloc( sz, 16); } INL PVOID __cdecl operator new [] ( size_t sz) { return _aligned_malloc( sz, 16); } INL void __cdecl operator delete( PVOID pVoid, size_t) { _aligned_free( pVoid); } INL void __cdecl operator delete( PVOID pVoid) { _aligned_free( pVoid); } INL void __cdecl operator delete [] ( PVOID pVoid, size_t sz) { _aligned_free( pVoid); } INL void __cdecl operator delete [] ( PVOID pVoid) { _aligned_free( pVoid); }
хз, мб легче тогдауж задефайнить _XM_NO_INTRINSICS_, чтобы матрица без выравнивания была, тогда краши прекращаются, но с другой стороны, правильно ли это
из МСДНа
When _XM_NO_INTRINSICS_ is defined, XNA Math operations are implemented without using any platform-specific intrinsics. Instead, XNA Math will use only standard floating point operations.
By default, _XM_NO_INTRINSICS_ is not defined.
Вахтанг Кикабидзе
c _XM_NO_INTRINSICS_ мат. библа не будет юзать SSE оптимизацию - глянь исходники и всё увидишь.
для записи значений в матрицы и вектора XNA надо использовать Load* и Save*
в "типизированные" объекты (например, FLOAT4X4) вроде можно свободно писать (см. документацию)
Столкнулся с примерно такойже проблемой, вот такой код вызывает краш:
m_testMatrix = XMMatrixIdentity();
но в тоже время работает такой код:
XMMATRIX m = XMMatrixIdentity(); memcpy( &m_testMatrix,&m,sizeof( m));
и не работает такой
XMMATRIX m = XMMatrixIdentity(); memcpy( &m_testMatrix,&m,sizeof( m)); m_testMatrix = m; //тут краш
при этом вполне можно обращаться к элементам матрицы так (без краша)
m_testMatrix._11 = 1.f m_testMatrix._22 = 1.f
но самое ужасное, что в одном примере из книжки вполнесебе хорошо работает такой код:
viewMatrix_ = XMMatrixIdentity(); projMatrix_ = XMMatrixPerspectiveFovLH( XM_PIDIV4, 800.0f / 600.0f, 0.01f, 100.0f ); viewMatrix_ = XMMatrixTranspose( viewMatrix_ ); projMatrix_ = XMMatrixTranspose( projMatrix_ );
Возможно ли, что это из-за того, что мой тип проекта - статическая либа, а пример нет?
и кстати #define _XM_NO_INTRINSICS_ не помогает :(
edit вообщем временно остался на memcpy. подскажите, в этом же нет чего-то ужасного в смысле по производительности?
tapahob
В первом случае объект находится в хипе, и скорее всего не выровнен.
Во втором случае единичная матрица формируется на стэке, где она выравнивается автоматически.
Для классов, содержащих SSE типы, нужно делать aligned allocator.
Суссюр
> Для классов, содержащих SSE типы, нужно делать aligned allocator.
Спасибо за ответ, aligned allocator вкатил, но нагуглился другой вариант
собственно вопрос, куда дописать этот параметр\ключ? пробовал в C\C++ -> Command line -> additional options и куда-то еще - не помогло.
tapahob
> собственно вопрос, куда дописать этот параметр\ключ? пробовал в C\C++ ->
> Command line -> additional options и куда-то еще - не помогло.
Не знаю кому как, но мне лично это пригодилось. Вдруг еще кто с таким вопросом встретиться
https://msdn.microsoft.com/ru-ru/library/7t5yh4fd.aspx
(если страницу когда-то удалят, то вот)
1) Откройте диалоговое окно Страницы свойств проекта.
2) Выберите папку Свойства конфигурации, а затем папку C/C++.
3) Выберете страницу свойств Создание кода.
4) Измените свойство Включить расширенный набор инструкций.
sawich
> Не знаю кому как, но мне лично это пригодилось. Вдруг еще кто с таким вопросом встретиться
Добро пожаловать в 21 век.
Тема в архиве.