잘못된 접근
범위를 벗어난 접근과 초기화되지 않은 값을 다룹니다
잘못된 접근은(는) CoddyKit의 무료 C Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
누수를 넘어
누수는 메모리를 낭비하지만 잘못된 접근 버그는 메모리를 손상시킵니다. memcheck는 다음과 같은 여러 문제를 찾아냅니다.
- 버퍼 끝을 넘어 읽거나 쓰기
free후 메모리 사용- 초기화되지 않은 값 읽기
- 잘못된 포인터를 통해 읽거나 쓰기
이러한 문제는 가장 위험하고 재현하기 어려운 충돌을 일으킵니다.
범위를 벗어난 쓰기
이 코드는 정수 5개를 저장할 공간을 할당하지만 인덱스 5, 즉 여섯 번째 위치에 씁니다.
인덱스 5는 끝에서 원소 하나만큼 벗어난 위치입니다. memcheck는 이 줄에서 Invalid write of size 4를 보고합니다.
#include <stdlib.h>
int main(void) {
int *a = malloc(5 * sizeof(int));
a[5] = 99; /* valid indices are 0..4 */
free(a);
return 0;
}오류 읽기
보고서에는 연산, 크기, 블록과의 관계가 표시됩니다.
Invalid write of size 4Address 0x... is 0 bytes after a block of size 20 alloc'd
'0 bytes after a block of size 20'이라는 문구는 접근이 20바이트(정수 5개) 할당 영역 바로 다음에서 발생했다는 뜻입니다.
범위를 벗어난 읽기
읽기도 감지됩니다. 여기서는 반복문이 원소 하나만큼 더 실행됩니다.
프로그램이 운 좋게 '정상 동작'할 수도 있지만, memcheck는 마지막 반복에서 Invalid read of size 4를 표시합니다.
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *a = calloc(3, sizeof(int));
for (int i = 0; i <= 3; i++) /* should be i < 3 */
printf("%d\n", a[i]);
free(a);
return 0;
}초기화되지 않은 값
malloc은 메모리를 0으로 초기화하지 않습니다. 값을 대입하기 전에 메모리를 사용하면 예측할 수 없는 값이 생성됩니다.
이 값이 제어 흐름이나 출력에 영향을 주면 memcheck는 Conditional jump or move depends on uninitialised value(s)를 보고합니다.
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *p = malloc(sizeof(int));
if (*p == 0) /* *p was never set */
printf("zero\n");
free(p);
return 0;
}초기화되지 않은 값의 보고가 늦는 이유
memcheck는 초기화되지 않은 메모리를 읽는 즉시 오류를 보고하지 않습니다. 값이 '정의되었는지'를 추적하다가 정의되지 않은 값이 분기, 출력 또는 시스템 호출처럼 실제로 중요한 역할을 할 때만 보고합니다.
따라서 초기화되지 않은 바이트를 문제없이 복사하는 경우에는 잘못된 경고를 피할 수 있습니다.
해제 후 사용
메모리를 해제한 후 해당 메모리에 접근하는 것은 정의되지 않은 동작입니다. memcheck는 이를 정확하게 감지합니다.
Invalid read of size 4를 보고하면서 Address ... is 0 bytes inside a block of size 4 free'd라는 설명도 표시하고, free가 실행된 위치까지 보여 줍니다.
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int *p = malloc(sizeof(int));
*p = 7;
free(p);
printf("%d\n", *p); /* read after free */
return 0;
}이중 해제
같은 포인터를 두 번 해제하면 할당자의 관리 정보가 손상됩니다.
memcheck는 Invalid free()를 보고하고 현재 해제와 원래 할당을 모두 표시하므로 실수를 쉽게 확인할 수 있습니다.
#include <stdlib.h>
int main(void) {
int *p = malloc(sizeof(int));
free(p);
free(p); /* freed twice */
return 0;
}출처 추적
초기화되지 않은 값 오류에는 --track-origins=yes를 추가합니다.
그러면 memcheck는 잘못된 값이 사용된 위치뿐 아니라 생성된 위치도 보고하므로, 모호한 경고가 정확한 수정 지점으로 바뀝니다.
valgrind --track-origins=yes ./prog스택과 전역 변수
memcheck는 HEAP 오류를 찾아내는 데 뛰어납니다. 하지만 stack이나 global arrays의 오버플로에 대해서는 검사 범위가 더 좁습니다.
이 경우에는 AddressSanitizer (gcc -fsanitize=address)가 더 나은 선택인 경우가 많습니다. 두 도구는 서로의 부족한 부분을 보완합니다.
경계에서 하나 초과: 널 종료 문자
자주 발생하는 HEAP 오버플로는 문자열 종료 문자를 잊는 것입니다. strlen은 'hello'에 대해 5를 반환하지만, 문자열은 끝에 붙는 '\0'을 저장하기 위해 6바이트가 필요합니다.
strcpy가 마지막 바이트를 끝을 넘어 기록하면 memcheck는 Invalid write를 보고합니다.
#include <stdlib.h>
#include <string.h>
int main(void) {
char *s = malloc(strlen("hello")); /* needs +1 */
strcpy(s, "hello"); /* writes the '\0' past end */
free(s);
return 0;
}빠른 확인
다음 코드 조각에 대해 memcheck가 무엇을 보고하는지 확인해 보세요.
복습
이제 잘못된 접근으로 발생하는 버그를 찾아낼 수 있습니다.
- 범위를 벗어난 읽기/쓰기는 블록 오프셋과 함께 Invalid read/write로 표시됩니다.
- 초기화되지 않은 값은 판단이나 출력에 영향을 줄 때 경고됩니다.
- 해제 후 사용과 이중 해제는 두 호출 위치와 함께 감지됩니다.
--track-origins=yes는 정의되지 않은 값의 출처를 정확히 찾아냅니다. 스택 버그에는 AddressSanitizer를 함께 사용합니다.
다음 단계: 전체 보고서 읽기
자주 묻는 질문
“잘못된 접근” 강의는 무료인가요?
네 — “잘못된 접근” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C Academy 강의 전체를 잠금 해제할 수 있습니다. C Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“잘못된 접근”에서 뭘 배우나요?
범위를 벗어난 접근과 초기화되지 않은 값을 다룹니다 브라우저에서 직접 실행하는 실습 코드로 C Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“잘못된 접근” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.