블로그 이미지
대갈장군

calendar

1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

Notice

2009. 7. 30. 00:53 프로그래밍
C에서 가장 많이 발생하는 오류가 아마도 메모리 관련 오류가 아닌가 싶은데 이는 여러가지 원인이 존재한다. 여러개의 클래스가 겹쳐지고 상속되고 난리를 치다보면 이중해제를 하는 실수는 누구나 할 수 있다. 

이 문서는 http://www.yolinux.com/TUTORIALS/C++MemoryCorruptionAndMemoryLeaks.html을 참조하여 작성되었다.

1. C/C++에서 메모리 오류의 종류

일단 메모리 공간에 따라 크게 Heap Memory 에러와 Stack (local variables) Memory 에러가 있다. Heap 메모리 영역에서 발생가능한 에러는,

  1. 이미 해제된 메모리 다시 해제 할때
  2. 할당된적도 없는 메모리 해제 할라고 할때
  3. 이미 해제된 메모리 영역에 뭔가 데이터를 쓰려고 할때
  4. 할당된 적이 없는 메모리에 뭔가 데이터를 쓰려고 할때
  5. 메모리 할당 에러
  6. 동적으로 할당된 메모리 배열에서 초과된 index의 위치를 읽거나 쓰려고 할때 

1,2 번과 3,4번을 묶어서 볼 수 있는데 해제시에 발생하는 문제 vs 데이터 입력시 발생하는 문제로 볼 수 있다.

스택 메모리 영역에서 발생가능한 에러들로는

  1. 정적 배열에서 초과된 index의 위치를 읽거나 쓰려고 할때
  2.  함수 포인터 오류인데 잘못된 함수 포인터의 전달로 인한 잘못된 함수 호출


2. 메모리 누수!

메모리 누수는 할당한 동적 메모리를 제대로 해제하지 않고 프로그램을 종료하면 발생하는 것으로써 이것이 지속되면 컴퓨터의 RAM (빠른 메모리 공간)을 모두 소모하여 버리고 Page 파일 (하드 디스크에 생성하는 가상 메모리)를 남발하게 되여 컴퓨터의 성능을 저하시키다 결국 넉다운 된다. 

우선 이 웹사이트에서는 strdup() 함수를 예를 들어 설명하는데 좋은 예인거 같지는 않다. 아무튼 말하고자 하는 점은 malloc() 함수 (C library)로 할당된 메모리는 반드시 free()로 해제하라는 점이다.

요약하자면, 
   1. new로 할당하면 delete로 해제, malloc으로 할당하면 free로 해제.
   2. 할당 실패하면 해제 하지 말것. (할당되지도 않은 놈 해제하면 당연히 에러)
   3. 상속될 가능성이 있는 클래스의 파괴자는 반드시 가상 함수로 선언하라
   4. 포인터 사이에 대입연산 (주소복사)는 항상 메모리 누수 및 이중 해제의 가능성을 가진다.
   5. 클래스의 대입 연산자 사용시 얕은 복사가 잃어난다면 (주소만 복사) 역시나 누수와 이중해제의 위험 존재.

3. 메모리 부패 (Memory Corruption)

참 단어 선택이 오묘한데 부패라고 하니 꼭 이상한 듯 들리지만 오염보다는 나은것 같아서 그렇게 표현했다. 한국어로 뭐라해야 할지 모르겠다.

Memory Corruption은 사용자가 부주의하여 명확한 할당 없이 주소에 접근하여 데이터를 변경하려 하거나 잘못된 주소 위치로 접근하려 하는 경우를 말한다. 즉, 컴퓨터 입장에서 보면 메모리가 '부패'한 셈이다 :)

우선 흔히 발생하는 Buffer Overflow의 경우는 할당된 메모리 양보다 더 많은 데이터를 집어 넣을때 발생하는 것이고 또 다른 흔한 Memory Corruption은 할당한 배열을 초과하는 위치에 접근하는 경우다. (인덱스 초과)

그리고 또 흔한 경우로 포인터 변수로 선언한 변수에 new로 메모리를 할당하지도 않았는데 포인터 주소가 가지는 멤버 변수나 함수로 접근하는 경우다. 당연히 에러다.

free() 함수로 날려버린 변수에 접근하는 것 역시 '부패한 메모리'로의 접근이다. 

생각보다 중요한 것이 나오는데 new []로 배열을 할당한 경우 반드시 delete []로 삭제해야 한다. 이거 의외로 실수하는 경우가 많다.

함수를 호출하여 함수 내에서 선언된 지역 변수의 주소를 넘겨와 사용할 경우 그 지역 변수는 함수 리턴 된 후에 언제든 사라질 수 있는 위험을 안고 있다. 그래서 절대로 이렇게 사용하면 안된다는 점.. 명심하자.











posted by 대갈장군