티스토리 뷰

C++/General

오류의 원인

엘키 2008. 1. 14. 15:27

* strcpy 등의 길이제한이 없는 함수는 사용하지 않는다

-> strncpy, memcpy와 같은 함수를 사용하고, 스트링 맨 끝에, 0을 넣어주는 것이 안전하다. 특히나 클라이언트에서 올라온 데이터는 더더욱 그렇다.

* 포인터 검사는 반드시 하라

-> 포인터 사용시에는 무조건 NULL포인터 검사를 하는 것이 좋다. 바로 쓰고 싶을 경우는 참조자를 사용해서 항상 유효한 데이터임을 알린다.

* 서식 지정자에 넣는 값에 유의하라.

-> 스트링 안에 %s %d 라는 코드가 있고, 가변 인자가 주어지지 않으면 에러가 발생한다.
%s 로 문자열을 입력 받으려 하는데, float형이나, int형을 입력했을 때에도 C는 널을 만나기 전까지 데이터 읽는 것을 멈추지 않는다. 잘못된 메모리를 접근 문제는 언제나 조심하자


* 포인터를 담는 자료구조에서, 해당 자료를 빼고, 포인터에 동작할당 된 주소를 delete할 때 주의하라

한 곳에서 new한 데이터를, 여러 곳에서 사용할 때 주의하라. new한 객체의 delete는 한 곳에서만 하라. delete된 포인터를 자료구조에서 들고 있으면 dangerous 포인터가 되니 조심하자.

* 배열 접근 시에는 무조건 범위 검사를 하라

배열 접근 인덱스는 반드시 유효한 값인지 범위 검사를 하라. 가급적이면 배열 접근 인덱스는 unsigned 한 값으로 사용해서, 배열 검사를 한번에 끝내는 것이 좋다.

* 인수로 넘어오는 문자열이나 배열의 값 복사시, 버퍼 크기에 유념하라.인수로 넘어온 값을 버퍼에 복사할 때, 넘어온 버퍼 크기도 고려하라.
받는 버퍼의 크기 검사도 물론 중요하지만, 넘어오는 값의 크기도 주의해야 한다. 넘어오는 버퍼의 크기를 넘겨 받거나 해서 그 크기만큼만 복사하도록 하자.

* 재귀적인 동작에 주의하라
재귀적으로 돌다 스택 오버 플로우가 나는 상황이나, 처리 과정이 맞물리다 재귀적으로 처리가 이뤄져 사용하는 메모리를 잃어 버리는 경우를 조심하라.

재귀로 인한 스택 오버 플로우는 말 할 필요도 없고, 재귀적으로 처리가 이뤄지다가 클래스 안이나, 힙에 잡힌 메모리의 주소를 사용하는 경우 프로그램의 비정상 동작이 원인이 될 수 있다.

혹시나 재귀적으로 돌아갈 여지가 생긴 경우에는 반드시 지역 변수로 선언해서 스택에 할당한 메모리를 사용하라.

* 정수형 값의 오버 플로우(또는 언더 플로우)도 주의하라
정수형 값이 오버 플로우 될 가능성은 언제든 존재한다.
그런 상황에서의 대처방법은 여러가지가 있겠지만 오버 플로우가 되는 상황은 늘 염두에 두어야한다.

생각하는 프로그래밍에서도 나왔듯이 생각보다 많은 프로그래머가 오버 플로우 버그가 있는 프로그램을 작성한다. 정수형도 포인터만큼 조심히 다루자.

*memcpy에 주의하라
memcpy시에 size가 음수가 되는 상황에 주의하라. 또한 NULL 포인터에서 (또는 NULL 포인터로) 복사되는 것에 주의하라.

*참조자는 신중히 사용하라.
참조자는 어떠한 변수를 가리킨다. 포인터와 마찬가지로, 가리키고 있는 대상이 사라지면 문제가 생긴다.
참조자보다 가리키고 있는 대상의 수명이 길어야 한다는 것을 잊지말라.

* HeapCorrupt 조심해라!
절대 delete된 곳에 access하거나, 할당한 범위를 넘어서서 접근하지 마라. 무슨일이 일어날지 모른다.

* 소멸자에서 가상함수를 호출하지 말아라.

가상 함수를 가지고 있을 때, 베이스 클래스의 소멸자에서 가상함수를 호출하면 pure virtual function call 문제가 생긴다.

* 상속을 염두에 두고 있다면, 가상 소멸자를 사용하라.
상속을 받은 상태에서 부모 클래스중에 어느 하나라도 가상 소멸자가 아니라면 pure virutal function call 문제가 생긴다.

* 스레드를 멈추는 시점을 베이스 클래스의 소멸자로 잡지 마라.
소멸자에서 스레드를 멈추고 싶다면, 구현 클래스에서 멈추게 하라. 베이스 클래스에서 스레드를 멈추게 할 경우 처리되고 있던 스레드에서 잘못된 가상 함수 호출을 할 여지가 있다.

* 구분자에 조심하라
일반적으로 데이터의 구분을 길이 + 데이터가 아닌, 스트림 형식으로 전달받을 경우 구분자가 존재한다.
이런 상황에서 데이터 내에 구분자가 존재하는 지를 반드시 검토해야 한다.
또한 구분자만으로 구성된 경우, 구분자가 없는 경우등의 다양한 상황도 테스트 해보고 검토하라.

'C++ > General' 카테고리의 다른 글

Interlocked 계열 함수  (2) 2008.01.18
시간 관련 함수 모음  (0) 2008.01.17
윈도우 가상 키 코드(Virtual Key Code)테이블  (0) 2008.01.12
BOOL을 쓰면 안되는 이유  (4) 2008.01.11
TCHAR to the rescue!  (0) 2008.01.11
댓글