[완료] 스택의 배열에 객체 초기화시 I/O BUS Error 를 왜 일으키는지 궁금합니다.

ikpil의 이미지

#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) 했는데, 왜 .. 더 작을 수도 있을까요?

dg의 이미지

g++ 4.1.2 에서 컴파일하고 실행해봤는데 아무 경고가 없네요. 도대체 어떤 환경에서 해보셨기에...

ikpil의 이미지

Exceptional C++ 내용이며, http://kldp.org/node/98951 관련 링크 참조 하시면 됩니다.

molla의 이미지

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를 내게 됩니다.

ikpil의 이미지

아! 그렇군요! 정말 통쾌하고 유쾌한 답변이였습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.