SlideShare uma empresa Scribd logo
1 de 10
alignment error(C4316)는 무엇이며 어떻게 해결하나
warning C4316: 'A' : object allocated on the heap may not be aligned 16
C4316 도대체 무엇인가!!
이를 위해서는 먼저 align에 대해 알아야 한다.
64bit컴퓨터에서 cpu가 한번에 처리할 수 있는 데이터 양은 64bit!!
결국 8byte씩 처리하는 게 제일 합리적.
(32bit에서는 4byte? align크기는 컴파일러 마다 다른 듯 하다.)
가령, 빨간 색 데이터를 읽어올 때,
http://www.songho.ca/misc/alignment/dataalign.html
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
얘는 한번 access에 가능하지만
얘는 두 번 데이터를 access해서 합쳐야 한다.
이러니 데이터들을 저장할 때 8byte크기에 맞춰두는 것이 성능 관점에서 유리할
수 밖에.. 이렇게 align은 특정 크기에 맞춰 데이터를 정렬시키는 것
그래서 우리 visual studio에서도 char double, int
로 13byte짜리 struct을 만들어도 알아서
이렇게 정렬을 해버린다.
참고로 데이터들 사이에 8byte를 맞추기 위해서
컴파일러가 알아서 넣어주는 부분을 padding이라
고 한다.
padding을 작게 하려면 struct을 만들 때, 크기가
작은 놈들부터 선언해두면 좋다.
필요에 따라서는 정렬할 크기를 바꿔야 할 때가 있다.
우리가 직면한 문제는 바로 matrix16인데 이 놈은 내
부적으로 정렬사이즈를 바꿔주는 함수
_declspec(align(16))이란 놈을 이용해서 16byte로 정
렬되고 있다.
그럼 MATRIX16은 왜 16BYTE 정렬을 하는가?!
우리가 선형대수에서 배운데로 행렬 연산을 하려면 행 열 별로 곱하고 더하고 지
지고 볶는 많은 연산들이 필요해 overhead가 크다.
근데 이러한 행렬 연산을 게임 등에서 많이 사용하므로 컴퓨터가 좋아지면서 이
런 행렬을 한 번에 처리할 수 있는 새운 명령어 집합이 추가되었다. (SSE라는 놈
으로 http://spy1233.tistory.com/47에서 누가 간단히 정리해두었으니 참고~)
이 SSE라는 놈이 16BYTE로 정렬된 데이터를 필요로 한다는 것!!
16BYTE 정렬된 데이터를 그냥 사용할 때는 문제가 없다.
문제는 HEAP영역에 할당할 때이다. vs 내장 NEW는 내부적으로 메모리를 할당
할 때 8byte allign을 사용해서 한다. 따라서 우리는 16byte align을 지원하는 new,
delete를 새로 만들거나 align되도록 보장해주어야 한다.
new 동작은 memory를 allocate하는 동작과
해당 객체의 생성자를 호출해주는 부분 두 가지로 나뉘어져 있다.
따라서 new할 때는 16byte 할당 후 생성자를 호출하고
m_pInstance = (T*)_aligned_malloc( sizeof( T ), 16 );
new (m_pInstance)T();
delete할 때는 역순으로 소멸자를 호출한 뒤 메모리를 free한다.
m_pInstance->~T();
_aligned_free( m_pInstance );
우리 프로젝트에서는 object들이 smart_pointer를 사용하고 있으므로 shared_ptr
에 deleter로 등록시켜주면 기본 delete동작 대신에 위의 동작을 수행하게 된다.
void DDObject::DeleteAlignedClass( DDObject* object )
{
object->~DDObject();
_aligned_free( object );
}
void DDObject::AddChild( DDObject* object )
{
auto deleter = DeleteAlignedClass;
std::shared_ptr<DDObject> object_ptr( object, deleter );
object->SetParent( this );
m_ChildList.push_back( object_ptr );
}
http://stackoverflow.com/questions/20104815/warning-c4316-object-
allocated-on-the-heap-may-not-be-aligned-16
No!!
malloc과 그의 친구들은 heap에 메모리를 할당할 때 8byte
만 보장해주기 때문에 16byte를 할당할 때 잘 될지 보장할 수
없어.
CPU에서 SSE 명령을 사용할 때 정렬되지 않은 데이터들이
문제가 될 수 있음
new랑 delete를 새로 만들어^^
_aligned_malloc(), _aligned_free() 쓰면됨
무시하면 어케됨?
원인이 뭐임?
어떻게 해결?
warning 4316이 뭔가요?
보장할 수 없을 만큼 많은 바이트가 할당되어 과도하게 정렬
된 struct에 대해 C4316이 발생 다음 장에 MSDN 문서 참고..
보장할 수 없을 만큼 많은 바이트가 할당되어 과도하게 정렬된 struct에 대해 C4316
이 발생

Mais conteúdo relacionado

Mais de quxn6

이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부quxn6
 
중급 소켓프로그래밍
중급 소켓프로그래밍중급 소켓프로그래밍
중급 소켓프로그래밍quxn6
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디quxn6
 
입체충돌처리
입체충돌처리입체충돌처리
입체충돌처리quxn6
 
introduce unity3D and playmaker basic
introduce unity3D and playmaker basicintroduce unity3D and playmaker basic
introduce unity3D and playmaker basicquxn6
 
TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디quxn6
 

Mais de quxn6 (6)

이펙티브 C++ 공부
이펙티브 C++ 공부이펙티브 C++ 공부
이펙티브 C++ 공부
 
중급 소켓프로그래밍
중급 소켓프로그래밍중급 소켓프로그래밍
중급 소켓프로그래밍
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
입체충돌처리
입체충돌처리입체충돌처리
입체충돌처리
 
introduce unity3D and playmaker basic
introduce unity3D and playmaker basicintroduce unity3D and playmaker basic
introduce unity3D and playmaker basic
 
TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디TCP echo 서버 및 클라이언트 예제 스터디
TCP echo 서버 및 클라이언트 예제 스터디
 

C4316 alignment error 해결

  • 1. alignment error(C4316)는 무엇이며 어떻게 해결하나 warning C4316: 'A' : object allocated on the heap may not be aligned 16
  • 2. C4316 도대체 무엇인가!! 이를 위해서는 먼저 align에 대해 알아야 한다. 64bit컴퓨터에서 cpu가 한번에 처리할 수 있는 데이터 양은 64bit!! 결국 8byte씩 처리하는 게 제일 합리적. (32bit에서는 4byte? align크기는 컴파일러 마다 다른 듯 하다.) 가령, 빨간 색 데이터를 읽어올 때, http://www.songho.ca/misc/alignment/dataalign.html 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 얘는 한번 access에 가능하지만 얘는 두 번 데이터를 access해서 합쳐야 한다. 이러니 데이터들을 저장할 때 8byte크기에 맞춰두는 것이 성능 관점에서 유리할 수 밖에.. 이렇게 align은 특정 크기에 맞춰 데이터를 정렬시키는 것
  • 3. 그래서 우리 visual studio에서도 char double, int 로 13byte짜리 struct을 만들어도 알아서 이렇게 정렬을 해버린다. 참고로 데이터들 사이에 8byte를 맞추기 위해서 컴파일러가 알아서 넣어주는 부분을 padding이라 고 한다. padding을 작게 하려면 struct을 만들 때, 크기가 작은 놈들부터 선언해두면 좋다.
  • 4. 필요에 따라서는 정렬할 크기를 바꿔야 할 때가 있다. 우리가 직면한 문제는 바로 matrix16인데 이 놈은 내 부적으로 정렬사이즈를 바꿔주는 함수 _declspec(align(16))이란 놈을 이용해서 16byte로 정 렬되고 있다.
  • 5. 그럼 MATRIX16은 왜 16BYTE 정렬을 하는가?! 우리가 선형대수에서 배운데로 행렬 연산을 하려면 행 열 별로 곱하고 더하고 지 지고 볶는 많은 연산들이 필요해 overhead가 크다. 근데 이러한 행렬 연산을 게임 등에서 많이 사용하므로 컴퓨터가 좋아지면서 이 런 행렬을 한 번에 처리할 수 있는 새운 명령어 집합이 추가되었다. (SSE라는 놈 으로 http://spy1233.tistory.com/47에서 누가 간단히 정리해두었으니 참고~) 이 SSE라는 놈이 16BYTE로 정렬된 데이터를 필요로 한다는 것!!
  • 6. 16BYTE 정렬된 데이터를 그냥 사용할 때는 문제가 없다. 문제는 HEAP영역에 할당할 때이다. vs 내장 NEW는 내부적으로 메모리를 할당 할 때 8byte allign을 사용해서 한다. 따라서 우리는 16byte align을 지원하는 new, delete를 새로 만들거나 align되도록 보장해주어야 한다. new 동작은 memory를 allocate하는 동작과 해당 객체의 생성자를 호출해주는 부분 두 가지로 나뉘어져 있다. 따라서 new할 때는 16byte 할당 후 생성자를 호출하고 m_pInstance = (T*)_aligned_malloc( sizeof( T ), 16 ); new (m_pInstance)T(); delete할 때는 역순으로 소멸자를 호출한 뒤 메모리를 free한다. m_pInstance->~T(); _aligned_free( m_pInstance );
  • 7. 우리 프로젝트에서는 object들이 smart_pointer를 사용하고 있으므로 shared_ptr 에 deleter로 등록시켜주면 기본 delete동작 대신에 위의 동작을 수행하게 된다. void DDObject::DeleteAlignedClass( DDObject* object ) { object->~DDObject(); _aligned_free( object ); } void DDObject::AddChild( DDObject* object ) { auto deleter = DeleteAlignedClass; std::shared_ptr<DDObject> object_ptr( object, deleter ); object->SetParent( this ); m_ChildList.push_back( object_ptr ); }
  • 9. No!! malloc과 그의 친구들은 heap에 메모리를 할당할 때 8byte 만 보장해주기 때문에 16byte를 할당할 때 잘 될지 보장할 수 없어. CPU에서 SSE 명령을 사용할 때 정렬되지 않은 데이터들이 문제가 될 수 있음 new랑 delete를 새로 만들어^^ _aligned_malloc(), _aligned_free() 쓰면됨 무시하면 어케됨? 원인이 뭐임? 어떻게 해결? warning 4316이 뭔가요? 보장할 수 없을 만큼 많은 바이트가 할당되어 과도하게 정렬 된 struct에 대해 C4316이 발생 다음 장에 MSDN 문서 참고..
  • 10. 보장할 수 없을 만큼 많은 바이트가 할당되어 과도하게 정렬된 struct에 대해 C4316 이 발생