모두의 코드
모두의 코드

총 42 개의 강의로 준비된 씹어먹는 C 언어 강좌를 통해 C 언어의 처음부터 끝까지 배우실 수 있습니다! 특히 악명 높은 C 언어의 포인터나, 어려운 개념들을 충실히 짚고 넘어갑니다.

이 강좌는 2010년에 완결되었지만, 지속적으로 개선 및 보완하고 있습니다.

C 언어 문법을 아시는 분들이라면, 씹어먹는 C++ 강좌를 통해 C++ 기초 부터 최근의 C++ 17 까지 모든 내용을 배우실 수 있습니다. C 언어와 C++ 의 기본적인 문법이 비슷하기 때문에, C 언어를 어느 정도 아는 독자를 가정하여 쓰여져 있습니다.

이 강좌는 2020년에 완결되었고 총 50 개의 강좌가 준비되어 있습니다.

사이트 내에서 검색 하기
C 언어 레퍼런스
표준 입출력 라이브러리 stdio.h
문자열 관련 라이브러리 string.h
시간 관련 라이브러리 time.h
C ++ 레퍼런스
문자열 라이브러리 string
알고리즘 라이브러리 algorithm
최근 댓글
void funcA() { int blah; MILF yermom; throw clsE( &yermom ); } void funcB() { try { funcA(); } catch( clsE const& objE ) { funcC(); objE.yermom->doit( "get lusty" ); } } 위 코드의 funcA() 에서 throw 되는 objE 개체는 funcA() 스택프레임의 top(주소값으론 가장 아래)에 생성되며, catch 블럭으로 점프하기 전에 blah 와 yermom 의 소멸자만 호출할 뿐 throw 되는 clsE 의 개체에 대해선 소멸자를 호출하지 않습니다. catch 블럭에서 objE 의 주소값을 확인해보면 funcB 의 스택프레임이 아니라 이미 소멸된 funcA 의 스택프레임 끝에 있음을 확인할 수 있구요.(스택프레임 날아간다고 거기 데이터를 지우는건 아니니까) void funcC() { char array1[1024]; blah.blah.blah; } 이 때 catch 블럭의 스택프레임은 funcA() 보다 아래쪽(주소상으론 위쪽)에 잡히지만, catch 블럭 내에서 호출되는 함수 funcC() 의 스택프레임은 objE 가 덮어쓰여지지 않도록 하기 위해 예외가 발생한 funcA() 스택프레임 끝 + sizeof(objE)의 위쪽(주소공간상으론 아래쪽)에 잡힙니다. 그러므로 catch 블럭에서 다른 함수를 호출한다고 objE 데이터가 덮여쓰여지거나 예외가 발생한 스택프레임이 덮어쓰여지는 경우는 없습니다. 단, 이 때 주의할 점은 throw 되는 개체가 물고 오는 개체들인데, 만약 clsE 와 MILF 가 아래와 같다고 가정할 때 struct clsE { clsE( MILF* pMilf ) : m_pMilf(pMilf) {} MILF* m_pMilf; }; struct MILF { MILF() { m_buf = new char[1024]; } ~MILF() { delete [] m_buf; m_buf = nullptr; } ... void doit( char *szFun ) { strcpy( m_buf, szFun ); } char *m_buf; }; funcA() 의 코드대로라면 throw 되는 clsE 의 개체는 이미 소멸자가 호출된 yermom 포인터를 물고 들어오게 되며, catch 블럭의 objE.yermom->doit(); 코드는 결과적으로 nullptr 에 쓰기를 시도하여 문제가 발생할 수 있습니다. 그러므로 예외 객체가 다른 개체를 물고 올 땐 가능한 포인터나 참조자가 아닌 사본을 갖고 오도록 설계하는게 좋습니다. 참고로... throw clsE( &yermom ); 위와 같이 throw 의 매개변수가 객체라면 생성자로써 스택에 생성된 개체가 catch 블럭에 전달되지만... clsE objE( &yermom ); throw objE; 위와 같이 개체를 전달할 경우엔 objE 개체 자체가 전달되지 않습니다. 그 대신 clsE 의 복사생성자로써 스택에 objE 개체의 사본을 생성해 catch 블럭에 전달하며, objE 개체 자체는 catch 블럭으로 점프하기 전에 소멸됩니다. static clsE objE(); objE.set( &yerrmom ); throw objE; 위와 같이 throw 의 매개변수가 static 개체일지라도 throw 문은 복사생성자로써 스택에 생성된 사본을 throw 합니다. (물론 의도적으로 이렇게 쓰는 경우도 있습니다. 예컨데 static objE 로써 마지막 예외정보를 따로 관리한다던가... catch 가 잡은 예외 개체는 블럭 벗어나면 소멸되므로.) 그러니 특별한 이유가 없는 한 throw 의 매개변수는 개체가 아닌 객체를 쓰는 쪽이 효율적입니다.
imyopapa 09.20