어느 저녁, 저는 야근을 하며 C++로 서버를 짜고 있었습니다. 이 부분만 끝나면 저는 일주일전 출시된 따근따근한 디아3에 접속해 아즈모단의 배때지를 천둥주먹으로 두들겨주려 성역으로 향할 예정이었기에 더욱 속도를 내었지만 어느 버그덕에 그날은 성역대신 구로디지털단지역에서 밤을 보내고 말게 되었습니다. <div><br></div> <div>저를 좌절시킨 버그는 이렇습니다. <br><div><br></div> <div><span style="font-size:9pt;line-height:1.5;">예를들어 Client 라는 클래스가 있고 Token이라는 멤버가 있었는데 어찌된건지 아무리 값을 세팅해줘도 0으로 읽어오는겁니다. </span></div> <div><br></div> <div>즉</div> <div>a.cpp</div> <div>client->Token=12345;</div> <div>...</div> <div><br></div> <div>b.cpp</div> <div><br></div> <div><span style="font-size:9pt;line-height:1.5;">if(client->Token!=0)</span></div> <div><span style="font-size:9pt;line-height:1.5;">{</span></div> <div>//어쩌고 저쩌고</div> <div><span style="font-size:9pt;line-height:1.5;">}</span></div> <div>else</div> <div>{</div> <div>//예외. </div> <div>ErrorLog("ASKY");</div> <div><span style="font-size:9pt;line-height:1.5;">}</span></div> <div><br></div> <div><span style="font-size:9pt;line-height:1.5;">라는 코드에서 무조건 ASKY만 찍어대는 신비한 현상이었습니다.</span></div> <div><br></div> <div><div><span style="font-size:9pt;line-height:1.5;">블랙홀이 따로 없습니다. 값을 아무리 넣어줘도 0이되버리니까요. 거기다 더 황당한건 VS로 </span><span style="font-size:9pt;line-height:1.5;">디버거로 break걸고 볼때는 또 정상입니다. Watch에 넣어봐도 client->Token | </span><span style="font-size:9pt;line-height:1.5;">12345 요렇게 또릿또릿 값을 뱉어냅니다.</span></div></div> <div><span style="font-size:9pt;line-height:1.5;"><br></span></div> <div><span style="font-size:9pt;line-height:1.5;">도무지 알 수가 없어서 메모리를 찍어보던 도중에 이상한걸 발견했습니다. 값을 세팅할때와 읽어올때의 Token 멤버에 번지수가 다르게 나오는 것이었습니다.</span></div> <div><br></div> <div>그래서 sizeof(Client)로 값을 찍어보니...</div> <div><span style="font-size:9pt;line-height:1.5;">값을 읽어서 비교하는 곳에서만 </span><span style="font-size:9pt;line-height:1.5;">1248 </span><span style="font-size:9pt;line-height:1.5;">바이트, 세팅하는곳에서는 </span><span style="font-size:9pt;line-height:1.5;">1256</span><span style="font-size:9pt;line-height:1.5;"> 바이트더군요. 똑같이 sizeof(Client) 그대로 찍었는데도요. 따라서 Token의 번지수가 밀려서 다른 값을 읽어오는 것이었습니다. </span><span style="font-size:9pt;line-height:1.5;">즉 sizeof(type) 이 값이 동적으로 다른것이었지요. </span></div> <div><span style="font-size:9pt;line-height:1.5;"><br></span></div> <div><div>참고로 sizeof(type)은 컴파일 타임에 결정되는 연산자 입니다. 즉 이미 프로그램이 실행되기 전에 컴퓨터는 이미 알고 있지요. 동적으로 바뀌지 않습니다. <span style="font-size:9pt;line-height:1.5;">적어도 제가 알고 있기론 그랬습니다. 그래서 더욱 알쏭달쏭. </span></div> <div><span style="font-size:9pt;line-height:1.5;"><br></span></div> <div><span style="font-size:9pt;line-height:1.5;">가상함수 테이블때문에 그러나, 아니면 static 멤버때문에 그러나... </span><span style="font-size:9pt;line-height:1.5;"> StackOverflow를 기웃기웃 바깥에서 바람한번 쐬고 다시와봐도 똑같은 값에 어안이 벙벙했습니다. 하다가 하다가 </span><span style="font-size:9pt;line-height:1.5;">성역에 가서 티리엘한테라도 물어볼까 고민도 했지요.</span></div> <div><br></div></div> <div>아무튼 삽질 끝에 발견한 원인은... 바로 </div> <div><br></div> <div>#pragma pack(1,push)요놈이었습니다. </div> <div><br></div> <div>클라이언트에 전송하는 패킷에 관려된 구조체 <span style="font-size:9pt;line-height:1.5;">packet.h에 </span><span style="font-size:9pt;line-height:1.5;">바이트정렬 문제로 저렇게 지시문을 넣었고 </span><span style="font-size:9pt;line-height:1.5;">pop을 안시켰고,</span></div> <div>그래서 include "packet.h" 밑으로 include된 애들은 전부 저 pragma에 영향을 받아 바이트정렬을 하지 않게 되고, 결국 include 순서에 따라 재멋대로 구조체의 크기가 잡히게 된겁니다. </div> <div><br></div> <div>모든 버그가 그러하듯이 잡고 나면 허무하지만.., 저때 허무함이란... </div> <div><br></div> <div>결론</div> <div>1.멤버값을 세팅해도 0으로 읽어오느 현상 발생</div> <div>2.원인찾다 sizeof(type)이 여기저기서 달라지는 현상보고 맨붕</div> <div>3.결국 원인은 #<span style="font-size:9pt;line-height:1.5;">pragma pack(1) 꼭 선언 끝나고 다시 되돌려 두자. (#</span><span style="font-size:9pt;line-height:1.5;">pragma pack(pop) or #</span><span style="font-size:9pt;line-height:1.5;">pragma pack()</span></div> <div><br></div> <div><br></div> <div><br></div> <div><br></div> <div><div><br></div></div></div>