그러나 File이나 Network에서 쓰일 고정길이 레코드 개념으로 쓰다보면 4바이트 단위 패딩은 매우 위험하다. 따라서 컴파일러마다 지시자를 두어 1바이트 단위로 패딩할 수 있게 하였다.
GCC는 __attribute__((__packed__)) 지시어를 이용하지만 GCC에만 적용하는 것이고, 일반적으로 VC에서 사용하던 지시자인 #pragma pack을 사용한다.
사용법은 아래와 같다.
#pragma pack(push, 1)
// ... definition ...
#pragma pack(pop)
또는
#pragma pack(1)
// ... definition ...
#pragma pack()
그런데 이러한 Data structure alignment가 Template과 결합하면 심각한 버그를 만들어낸다.
* 2002년에 보고한 내용인데, 2009년에 수정한 GNU GCC팀의 패기에 박수를 보낸다. (응?)
#include
using namespace std;
#pragma pack(1)
template<typename _T>
struct mystr_t
{
_T otype;
int i;
};
#pragma pack()
#pragma pack(1)
struct inner_t
{
char c[3];
};
#pragma pack()
int
main(int argc, char* argv[])
{
cout << "sizeof(inner_t): " << sizeof(inner_t) << endl;
mystr_t<inner_t> tmp;
cout << "sizeof(tmp): " << sizeof(tmp) << endl;
#pragma pack(1)
mystr_t<char[3]> tmp2;
cout << "sizeof(tmp2): " << sizeof(tmp2) << endl;
#pragma pack()
mystr_t<unsigned char[3]> tmp3;
cout << "sizeof(tmp3): " << sizeof(tmp3) << endl;
}
위 코드는 Template이 실제 코드로 구현(instantiatiion)할 때마다 pragma pack이 적용되어 어떠한 경우에도 "7"을 출력해야 정상이다. 그러나 버그가 있는 GCC는 2번째를 제외하고 모두 "8"을 출력한다.
버그이고, 회피 방법은 앞서 말한 __attribute__((__packed__))를 사용하는 방법이 있지만, 소스코드가 지져분해지고 매우 귀찮다. 아니면 GCC를 4.5.1 이후 버전을 사용하는 방법도 있다.
* 해당 버그 히스토리: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7046
* 참고로 해당 버그가 GCC외에도 꽤 많은 C++ 컴파일러에 존재하였고, 현재는 유명한 컴파일러는 모두 수정한 상태이다.
댓글 없음 :
댓글 쓰기