기본 패턴
text
1. 경계 밖 접근이 있었는가?
2. 이미 free 한 포인터를 다시 썼는가?
3. NULL 또는 초기화되지 않은 포인터를 역참조했는가?
4. malloc 크기 계산이 틀렸는가?
5. AddressSanitizer / Valgrind로 재현되는가?설명
- C 디버깅에서 가장 어려운 점은 "에러가 난 위치"와 "문제가 시작된 위치"가 다를 수 있다는 것입니다. 특히 메모리 버그는 손상이 나중에 다른 코드에서 폭발하는 경우가 많습니다.
- 대표적인 패턴은 버퍼 오버런, off-by-one, use-after-free, double free, 초기화되지 않은 포인터 사용, 잘못된
sizeof계산입니다. 대부분은 포인터와 길이, 소유권을 함께 보지 않을 때 생깁니다. - 그래서 디버깅도 순서가 중요합니다. 먼저 마지막으로 메모리를 만진 코드, 버퍼 길이 계산,
malloc과free짝, 함수 인자로 전달된 포인터 유효 범위를 확인하는 편이 좋습니다. - 현대 개발 환경에서는 sanitizer와 동적 분석 도구가 큰 도움을 줍니다. AddressSanitizer는 경계 밖 접근과 use-after-free를 빠르게 잡아 주고, Valgrind는 누수와 잘못된 메모리 사용을 추적하는 데 유용합니다.
- 교재 수준에서 정말 중요한 것은 "포인터 하나"가 아니라 "메모리의 소유자, 길이, 유효 기간"을 함께 보는 사고입니다. 이 세 가지를 문서처럼 머릿속에 붙잡는 습관이 디버깅 시간을 크게 줄입니다.
빠른 정리
| 의심 포인트 | 먼저 볼 것 |
|---|---|
| segfault | NULL, 경계 밖 접근, 이미 해제된 포인터 |
| 값이 이상함 | 잘못된 크기 계산, 메모리 덮어쓰기 |
| free 관련 오류 | double free, 소유권 중복 |
| 누수 | malloc/calloc/realloc 이후 해제 경로 확인 |
| 도구 | AddressSanitizer, Valgrind |
주의할 점
메모리 버그는 "터진 줄"만 고치면 다시 비슷한 곳에서 재발하는 경우가 많습니다. 증상보다 먼저 길이, 소유권, 생명주기라는 세 축을 체계적으로 다시 확인하는 편이 훨씬 효과적입니다.
참고 링크
2 sources