2012년 독서 목록
gcc/g++ strict aliasing
오늘 회사에서 알게 된 것. 사용한 gcc/g++는 4.1.2인데 3.4.6이나 4.5.1에서 발생하지 않은 걸로 보아 컴파일러 버그일 수도 있다.발단은 아래와 비슷한 코드를 컴파일할 때 최적화 옵션 여부에 따라 결과가 달라지는 현상.float function(float val) {int* ptr = (int)&val;ptr = (a number N1)val = f(val);return val;}기대한 값은 val과 ptr가 같은 메모리 주소에 있으므로 *ptr에 할당된 N1이 다음 문장에서 val에 반영되어 있는 상태로 계산한 결과인데, 최적화 옵션이 없으면 기대한 결과가 나오지만, -O2 옵션 이상에서는 전혀 다른 값이 반환됨.원인:gcc/g++의 옵션 중 -O2에서 추가되는 -fstrict-aliasing.gcc 문서에 따르면”Allow the compiler to assume the strictest aliasing rules applicable to the language being compiled. For C (and C++), this activates optimizations based on the type of expressions. In particular,an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same. For example, anunsigned intcan alias anint, but not avoidor adouble. A character type may alias any other type.”쉽게 말해 서로 다른 타입의 포인터를 reference/dereference하는 게 (항상 그런 건 아니지만) 위험하다는 얘기. 덧붙여 변수의 주소를 다른 타입 포인터로 변환한 뒤 참조하면 미정의 동작을 한다고 한다.위 코드에서도 ptr가 val의 주소를 integer pointer로 취한 다음 값을 변경하지만 이것이 실제로 val에는 반영이 안된다. 어셈블리 코드를 확인해보면 *ptr에 값이 대입하는 부분이 빠진다. 아마도 ptr와 val를 연관짓지 않고 쓰이지 않는 변수로 판단해서 최적화 과정에서 없앤 것 같다.다행히(?) 내가 짠 코드는 아니고 협업 도중 이상한 결과가 보여서 파보니 이렇더라는 얘기다. 그래도 비교적 짧은 시간에 재밌는 사실을 배웠다. 다만 나도 예전에 저런 식으로 pointer casting을 종종 했는데 앞으로는 무서워서 함부로 못하겠네.참고로 -Wall 옵션으로 컴파일러 경고를 최대로 하면 이에 대한 경고가 뜬다. 물론 4.1.2에서만 해당되는 이야기.덧) 왜 들여쓰기가 안되지. 코드도 그렇고 인용문도 그렇고. 스킨을 바꿔야 하나.
- 2012/02/15 21:39 에 작성