고수닷넷 - 데미소다오렌지님
1. Introduction
활성화된 프로그램관련 질답 게시판을 보면 반복적으로 늘 올라오는 질문중의 하나가 메모리 오류에 관한 것 이다. 실무에 사용되는 대부분의 상용 프로그램들도 포인터/메모리 관련 코드들이 프로그램의 전체 오류의 90% 이상을 차지한다고해도 과언이 아니다. 실무 프로그램이 이정도니 처음 작성하는 사람들이 포인터 오류를 피한다는 것은 그야말로 힘들다고 할 수 있다. 또한 오류 상황을 보고 대처하는 방법을 모르기 때문에 더욱 난처한 경우가 많다. 아마도 그래서 질답 게시판에는 그렇게나 자주 뜬금없는 질문들이 많이 올라오는 것으로 보인다.
이 문서는 오류가 나는 코드를 살펴보고, 해당 코드가 실행될때 발생하는 오류를 알아 봄으로써 추후에 동일한 에러가 난 경우에 좀 더 빨리 디버깅 할 수 있는 능력 배양에 그 목적이 있다 하겠다... ㅎㅎㅎ~ 그럼 지금부터 처음 프로그램을 작성하는 분들이 자주 접하는 메모리 오류 상황에 대해서 살펴보도록 하자~
2. Heap overrun
첫번째는 메모리 영역을 넘어서 오버라이트 한 경우이다. 다음과 같은 코드를 생각할 수 있다.
void stupid_func(int *ar)
{
memset(ar, 0, sizeof(int) * 200);
}
int main()
{
int *ar = new int[100];
stupid_func(ar);
delete [] ar;
return 0;
}
보면 100개를 할당하고 나서는 stupid_func에서 200개를 초기화 해버리고있다. 할당된 것 보다 더 많이 써서 오버라이트 되 버린 것이다. 디버그 중이라면 아래와 같은 ASSERT 진단 오류를 만날 수 있다.
3. Heap header overwrite
두번째로 할당된 메모리 이전 영역을 겹쳐쓰는 경우이다. 다음과 같은 코드를 생각할 수 있다.
void stupid_func(int *ar)
{
memset(ar-100, 0, sizeof(int) * 200);
}
int main()
{
int *ar = new int[100];
stupid_func(ar);
delete [] ar;
return 0;
}
보면 할당이 시작된 주소 이전(ar-100)에서 부터 값을 채우기 때문에 라이브러리에서 내부적으로 사용하는 관리 헤더 부분을 초기화 시킬 수 있다. 디버그 중이라면 아래와 같은 ASSERT 진단 오류를 만날 수 있다.
4. More...
아래는 위의 것과 유사한 오류가 날 수 있는 더 많은 상황들을 정리해 보았다. 늘 항상 포인터를 다룰때에는 아래와 같은 점검 목록을 머릿속으로 생각하는 것을 게을리 하지 말아야 할 것이다.
-
malloc/free와 new/delete를 혼용해서 사용하는 경우. malloc으로 할당해서 delete로 지우는 경우 등이 해당한다.
-
delete/delete [] 혼용. delete는 단일 원소 삭제에, delete []은 배열 원소 삭제에 사용해야 한다. 이 둘을 잘못 사용해서는 안된다.
-
할당된 포인터 값 변경. 100번지에 할당받아 놓고, delete나 free시에 200번지를 입력하는 경우다. 이런 경우는 대부분 할당 받은 포인터를 for루프등에 사용함으로써 발생한다. 할당받은 포인터는 절대로 값을 변경해서는 안된다. 값을 변경하고 싶으면 복사해서 임시 변수로 참고하도록 한다.
5. Conclusion
C++을 사용한다면 되도록 날(Raw) 포인터를 사용하지 않는 것이 좋다고 한다. 그리고 날(Raw) 포인터를 사용해야 한다면 그 놈이 사용되는 코드 주위는 항상 감시하도록 하자!
- 실행시 메모리 점유율 줄이기. (0)2006/12/29
- 시스템 트레이 사용하기 (0)2006/12/29
- 메모리 오류 (0)2006/12/27
- 파일 버전 구해서 비교하기... (0)2006/12/08
- 재밌는 시스템 강제로 다운시키기 (0)2006/12/08

수안이의 컴퓨터 연구실




Leave your greetings.