배열과 문자열: 버퍼 넘침의 원리
배열은 메모리에 연속으로 놓인 같은 자료형의 묶음이고, 문자열은 널 문자로 끝나는 char 배열입니다.
배열
uint8_t buf[8];은 8바이트가 연속으로 놓인 공간입니다. buf[i]는 "시작 주소에서 i칸 뒤"라는 뜻일 뿐이라 C는 범위를 검사하지 않습니다. buf[8]에 쓰면 배열 바로 뒤에 있던 다른 변수가 망가집니다. 이것이 버퍼 넘침입니다.
문자열
C의 문자열은 끝에 '\0'이 붙은 char 배열입니다. "OK"는 세 바이트를 차지합니다.
char msg[16];
snprintf(msg, sizeof msg, "T=%d", temp); // 크기를 넘기지 않음
strcpy, sprintf처럼 길이를 확인하지 않는 함수 대신 strncpy, snprintf를 씁니다.
임베디드에서 배열이 쓰이는 곳
- UART 수신 버퍼, 통신 패킷
- ADC 샘플을 모아 평균 내는 버퍼
- 룩업 테이블과 설정값 표
배열 크기는 매크로 하나로 정하고 루프 조건도 그 매크로를 쓰면, 크기를 바꿀 때 실수가 줄어듭니다.
그림으로 보기: 문자열의 끝은 0이다
C의 문자열은 길이를 따로 저장하지 않습니다. strlen, printf("%s"), strcpy는 모두 0을 만날 때까지 메모리를 읽어 나갑니다. 0이 없으면 배열을 지나 옆 변수까지 읽거나 씁니다.
버퍼 넘침이 실제로 일어나는 모습
char cmd[8];
uint8_t motor_enable = 0;
void on_uart_line(const char *line) {
strcpy(cmd, line); // line이 8글자 이상이면 cmd를 넘어 씀
}
cmd 바로 뒤에 motor_enable이 놓였다면, 긴 문자열 하나로 그 값이 바뀝니다. 통신으로 들어온 데이터는 길이를 믿을 수 없으므로 항상 크기를 넘겨 제한합니다.
size_t n = strnlen(line, sizeof(cmd) - 1);
memcpy(cmd, line, n);
cmd[n] = '\0'; // 끝을 직접 채움
3D 실험실여기까지 읽은 내용을 직접 돌려 볼 수 있습니다→안전한 함수로 바꾸기
| 위험 | 대신 쓸 것 | 주의 |
|---|---|---|
strcpy |
길이를 재고 memcpy |
끝의 0을 직접 넣기 |
sprintf |
snprintf(buf, sizeof(buf), ...) |
반환값이 크기 이상이면 잘린 것 |
strncpy |
위와 같음 | 꽉 차면 0을 넣지 않음 |
gets |
쓰지 않음 | 길이 제한이 아예 없음 |
strncpy는 이름과 달리 안전하지 않습니다. 원본이 버퍼보다 길면 끝에 0을 넣지 않고 그대로 돌아옵니다.
배열을 함수에 넘기면 크기가 사라진다
void clear(uint8_t buf[]) {
memset(buf, 0, sizeof(buf)); // 틀림: 포인터 크기(4)만큼만 지움
}
void clear2(uint8_t *buf, size_t len) { memset(buf, 0, len); } // 길이를 함께 넘김
함수 인자로 받은 배열은 포인터입니다. sizeof는 배열 전체가 아니라 포인터 크기를 돌려줍니다. 배열을 받는 함수는 길이를 함께 받도록 만듭니다.
배열의 칸 수는 선언한 곳에서 이렇게 구합니다.
#define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0]))
인덱스 검사는 쓰기 전에
if (idx < ARRAY_LEN(table)) table[idx] = value;
통신으로 받은 채널 번호, 센서 ID처럼 바깥에서 온 값을 인덱스로 쓸 때는 반드시 범위를 확인합니다. C는 범위를 벗어나도 오류를 내지 않고 그 주소에 그대로 씁니다.
스스로 확인
char s[] = "hello";에서sizeof(s)와strlen(s)는 각각 얼마일까요?- 2차원 배열
uint8_t m[3][4]에서m[1][5]에 쓰면 어디에 쓰일까요?
영상으로 이어 보기공부법과 진로 시리즈 15편2025 임베디드 프로그래밍 공부 순서 | 공부 방법 | 로드맵PROJECT COURSEC 문법을 실제 펌웨어 코드로 써 보고 싶다면밸런싱 로봇 하나를 요구사항, 회로와 PCB, 펌웨어, 앱까지 실무 순서대로 만드는 강의입니다. 10파트 165강.강의 살펴보기 →FREE PDF무료 전자책 3권 받기이 주제를 한 권으로 이어서 읽고 싶다면. BLDC 모터 제어, 직렬통신, 센서를 책 분량으로 묶었습니다. 이메일만 남기면 바로 받습니다.무료로 받기 →