C, C++, Pascal 등과 같은 저수준 프로그래밍 언어에서 자주 발생
일반적으로 포인터 연산이 잘못된 경우에 발생
메모리 관리와 연관이 있다
메모리 누수가 발생, 새로 선언한 변수가 기존 변수의 메모리 영역을 침범
널 포인터 참조
포인터가 유효하지 않은 메모리 주소를 가리키거나 널(NULL) 포인터를 참조할 때 발생
포인터를 사용하기 전에 반드시 유효한 메모리 주소를 가리키는지 확인
해제된 메모리 접근
이미 해제된 메모리 블록을 접근하려고 할 때 발생
free()나 delete로 메모리를 해제한 후, 해당 포인터를 다시 사용하려고 하면 문제가 발생.
메모리 오버플로우
배열의 범위를 넘어서는 메모리 접근이 있을 때도 이 에러가 발생
배열의 크기를 초과하는 인덱스를 사용할 때 이런 문제가 발생.
잘못된 포인터 연산
포인터 산술 연산을 잘못 수행했거나, 잘못된 포인터 연산으로 인해 메모리의 잘못된 위치를 참조했을 경우
이외에도 포인터를 직접적으로 실수하지 않았다고 해도 발생하는데
스택 오버플로우
함수 호출 시 너무 깊은 재귀 호출이나 너무 큰 지역 변수를 사용하는 경우 스택 오버플로우가 발생
이는 포인터와 관련이 없지만, 프로그램에서 예상치 못한 오류를 발생시킬 수 있다
형 변환 문제
잘못된 형 변환으로 인해 데이터가 손상되거나 잘못된 메모리 주소를 참조할 수 있다
예를 들어, int*를 float*로 변환하여 사용하면 문제가 발생할 수 있다
메모리 할당 실패
malloc이나 new로 메모리를 할당했지만 할당이 실패하거나 메모리 부족 상태가 발생한 경우에도 문제가 생길 수 있다
이러한 경우 메모리 할당 후 반환값을 확인
타이밍 문제 (동시성 문제)
멀티스레딩 프로그램에서 스레드가 동시에 메모리에 접근하거나 수정할 때 문제가 발생할 수 있다
데이터 손상
프로그램에서 데이터를 잘못 처리하거나 수정하는 과정에서 메모리 손상이 발생할 수 있습니다. 예를 들어, 배열의 크기를 넘어서는 데이터를 쓰는 경우.
만약 프로그램 종료시 발생한다면,
객체가 해제되고, 다른 이벤트 혹은 스레드에서
이 객체로 다시 접근을 했을 가능성이 높다
해결법으로
포인터 초기화
포인터를 선언할 때, 바로 유효한 메모리 주소를 할당하거나 초기값을 설정
예를 들어, C/C++에서는 nullptr(C++11 이상) 또는 NULL을 사용하여 초기화
해제 후 포인터 설정
메모리를 해제한 후에는 포인터를 nullptr로 설정하여 나중에 이 포인터를 참조하지 않도록 한다
배열 경계 체크
배열을 사용할 때는 항상 배열의 크기를 확인하고 인덱스가 범위를 초과하지 않도록 주의
디버거 및 도구 사용
디버거
디버거를 사용하여 코드 실행 중 문제가 발생하는 위치를 추적하여 프로그램이 중단된 위치와 포인터의 상태를 확인
이를 통해 포인터가 잘못된 메모리 위치를 참조하는지 확인할 수 있다
메모리 검사 도구
Valgrind, AddressSanitizer 등과 같은 도구를 사용하여 메모리 오류를 찾을 수 있다
C++ Builder는 델파이와 같은 런타임 라이브러리를 사용하여 메모리 관리를 수행