Journey to Security/C언어

C언어 char 배열의 메모리 할당 및 문자열 초기화 메커니즘 (feat. VS Code 디버거)

Cordilog 2026. 2. 11. 18:13

C언어에서 문자열 배열을 다룰 때, 선언과 동시에 값을 대입하는 것과 선언 후 별도로 대입하는 것은 메모리 관점에서 차이가 있다.

VS Code의 디버거를 통해 각 케이스별로 메모리 내부의 쓰레기값과 데이터 배치 과정을 확인해볼 수 있다.

 

1. 테스트 코드 작성

비교를 위해 두 가지 케이스를 구성했다. CASE 1은 선언과 동시에 초기화하는 방식이고, CASE 2는 선언 후 strcpy 함수를 사용하여 값을 대입하는 방식이다.

디버거의 변화를 관찰하기 위해 message1[10] 배열 초기화 부분에 중단점(Breakpoint)을 걸어주고 F5로 디버깅을 실행한다.

#include <stdio.h>
#include <string.h>

int main() {
    // [CASE 1] 선언과 동시에 초기화
    char message1[10] = "Hello!";

    // [CASE 2] 선언 후 나중에 값을 대입
    char message2[10];
    // 이 시점에서 message2의 메모리 상태를 확인해야 함
    strcpy(message2, "Hi!");

    return 0;
}

 

2. VS Code 디버거를 통한 메모리 추적

[CASE 1] 선언과 동시에 초기화 (char message1[10] = "Hello!";)

이 방식은 컴파일러가 배열의 생성과 데이터 주입을 한 번에 처리한다.

    • 데이터 배치: 인덱스 0~5까지 H, e, l, l, o, !가 저장된다.
    • 널 종단 문자: 인덱스 6에 \0 (ASCII 0)이 자동으로 삽입된다.
    • 남은 공간의 처리: 배열 크기(10) 중 사용되지 않은 인덱스 7~9 영역은 모두 0(Nul)으로 자동 초기화된다. 즉, 메모리가 매우 깔끔하게 정리된 상태를 유지한다.

 

[CASE 2] 선언 후 나중에 값을 대입 (char message2[10]; → strcpy)

이 방식은 메모리 할당과 데이터 복사가 별개의 시점에 이루어진다.

 

1. 선언 직후 (Pause Point):

message2[10] 선언 직후 디버거로 내부를 들여다보면, 10바이트 전체가 의미 없는 쓰레기값(Garbage Value)으로 차 있다.

 

2. strcpy 실행 후:

  • Hi!와 널 문자(\0)가 포함된 총 4바이트가 배열 앞부분에 덮어씌워진다.
  • 잔류 쓰레기값: strcpy는 널 문자를 만나는 즉시 복사를 중단한다. 따라서 인덱스 4부터 9까지는 선언 당시에 있던 쓰레기값이 그대로 남아 있게 된다.

 

 

3. 기술적 데이터 요약 및 비교

디버깅 도중 [Watch] 창이나 [Memory View]에서 관찰되는 실제 데이터 구조는 다음과 같다.

비교 항목 CASE 1 (선언 시 초기화) CASE 2 (선언 후 대입)
명령어 char m[10] = "Hello!"; char m[10]; strcpy(m, "Hi!");
메모리 시작점 데이터 즉시 주입 할당 시점에는 쓰레기값 존재
널 문자 처리 자동 삽입 strcpy가 복사 과정에서 삽입
미사용 공간 0으로 자동 초기화 기존 쓰레기값 유지
안전성 상대적으로 높음 버퍼 오버런 위험 존재

 

4. 주의사항

위와 같이 VS Code 디버거를 통해 확인한 결과, C언어 배열은 초기화 시점에 따라 메모리 상태가 다름을 알 수 있다.

  1. 초기화의 중요성: 예측 불가능한 동작을 방지하려면 선언 시 char message[10] = {0, };와 같은 방식으로 명시적 초기화를 수행하는 것이 좋다.
  2. 널(Nul) 문자의 역할: 어떤 방식이든 문자열의 끝에는 널 문자(\0)가 존재해야 하며, 이를 위해 배열 크기는 항상 (문자열 길이 + 1) 이상이어야 한다.
  3. 대입의 한계: message2 = "Hi!";와 같은 직접 대입은 배열명(상수 포인터)의 특성상 문법적으로 허용되지 않으므로, 반드시 strcpy 같은 메모리 복사 함수를 사용해야 한다.