[완료] 스택의 배열에 객체 초기화시 I/O BUS Error 를 왜 일으키는지 궁금합니다.
글쓴이: ikpil / 작성시간: 금, 2008/10/17 - 4:40오후
#include iostream #include new class Base { public: Base() { std::cout << "Base::Base() 호출" << std::endl; } virtual ~Base() { std::cout << "Base::~Base() 호출" << std::endl; } virtual void vDraw( void ) { std::cout << "Base::vDraw 호출" << std::endl; } void Draw( void ) { std::cout << "Base::Draw( ) 호출" << std::endl; } private: int a; }; class Derived : public Base { public: ~Derived() { std::cout << "Derived::~Derived() 호출" << std::endl; } Derived() { std::cout << "Derived::Derived() 호출" << std::endl; } virtual void vDraw( void ) { std::cout << "Derived::vDraw 호출" << std::endl; } void nvDraw( void ) { std::cout << "Derived::nvDraw 호출" << std::endl; } private: int b; }; int main( void ) { // Derived 크기 만큼 char 배열로 잡음 char object[ sizeof( Derived ) ]; // object 자리에 Derived() 생성자 호출 Base* pB = new (&object[0]) Derived(); // 가상 함수 호출 시도 pB->vDraw(); // Base::Draw() 호출 시도 pB->Draw(); // Derived* 로 형 변환 시도 Derived* pD = static_cast<Derived*>(pB); // Base::Draw() 호출 시도 pD->Draw(); // Derived::vDraw() 호출 시도 pD->vDraw(); // Derived::nvDraw() 호출 시도 pD->nvDraw(); // 소멸자 명시적 호출(왜냐하면 object는 char형이므로) pD->~Derived(); }
위 코드중 placement new 사용시 I/O bus 오류가 일어날 수 있다고 경고 하고 있습니다. 왜냐하면 스택에 올린 고정길이 배열의 크기가 Derived 객체의 크기보다 작을 수 있기 때문이라고 하는데, 왜 더 작을 수 있는지 모르겠습니다.
질문입니다.
sizeof(Derived) 했는데, 왜 .. 더 작을 수도 있을까요?
Forums:
g++ 4.1.2 에서
g++ 4.1.2 에서 컴파일하고 실행해봤는데 아무 경고가 없네요. 도대체 어떤 환경에서 해보셨기에...
Exceptional C++
Exceptional C++ 내용이며, http://kldp.org/node/98951 관련 링크 참조 하시면 됩니다.
http://www.ikpil.com
c++ 구문이라 헷갈리긴 합니다만...
BUS error 는 보통 align이 안 맞았을 때 발생합니다.
링크된 글의 링크된 글을 보면 나와 있습니다만, 결국 align 문제인듯 합니다.
일반적인 CPU 에서는 4byte 자료구조체 (int 등)는 주소값이 4byte로 align 되어 있어야 합니다. 8byte 자료 구조체는 8byte 주소로 align이 되어 있어야 하지요.
따라서 일반 변수 선언을 하거나 할 때엔 compiler 가 알아서 align된 주소로 할당해 줍니다. malloc 등과 같은 함수는 아예 8byte align된 주소를 돌려주도록 되어 있구요. (할당된 memory가 어떤 type으로 사용될 지 모르므로 무조건 최대 크기로 align된 주소를 돌려줍니다.)
그런데 위와 같이 char 형식으로 stack 변수를 선언하면, char type 은 1byte align만 맞으면 되기 때문에 align이 안 맞는 주소를 돌려받을 확률이 매우 높습니다.
그런 주소를 다른 type으로 형변환해서 사용하면 CPU에 따라 align이 안 맞는다고 BUS error 가 발생하는 것이지요.
CPU 에 따라 다르다는 것은. 우리가 많이 사용하는 X86 에서는 기본적으로 align이 안 맞아도 BUS error를 안 내기 때문입니다. (설정하면 bus error를 낼 수도 있습니다만, 그렇게하면 OS 부팅조차 안 될 것입니다. -ㅅ-) 하지만 그 외 대부분의 CPU 에서는 align이 안 맞으면 BUS error를 내게 됩니다.
아! 그렇군요! 정말
아! 그렇군요! 정말 통쾌하고 유쾌한 답변이였습니다.
http://www.ikpil.com
댓글 달기