Journey to Security/C언어

C언어 배열 메모리 레이아웃 (feat. GDB)

Cordilog 2026. 2. 20. 08:58

C 언어에서 배열이 메모리에 어떻게 저장되고 관리되는지 GDB(GNU Debugger)를 실행해서 눈으로 직접 확인해볼 수 있다.

1. 배열 코드

배열을 사용하지 않았을 때와 사용했을 때의 차이를 보여주는 예제 코드이다.

배열을 사용하면 반복문을 통해 효율적으로 데이터에 접근할 수 있다는 장점이 있다.

#include <stdio.h>
int main() {
    // 배열을 사용하지 않은 경우
    int a, b, c, d, e;
    a = 1, b = 2, c = 3, d = 4, e = 5;
    
    // 배열을 사용한 경우
    int number[5] = {1, 2, 3, 4, 5};
    
    printf(">>> 반복문으로 배열 출력 <<<\n");      
    for(int i = 0; i < 5 ; i++ )
        printf("%d\n", number[i]);
    return 0;
}

 

2. GDB 디버깅 과정 및 명령어

소스 코드 확인 및 브레이크포인트 설정

  • list: 소스 코드의 내용을 출력한다.
  • return 0; 이 해당하는 라인 번호를 확인하고 해당 라인에 중단점을 설정한다. (ex. b 13) 프로그램 종료 직전의 메모리 상태를 확인하기 위함이다.
  • r (run): 프로그램을 실행한다.

 

변수 및 주소 값 확인

  • p number (print): number 배열 전체의 요소를 출력한다.
  • p &number: 배열 전체를 가리키는 포인터 주소를 확인한다.
  • p number[0]: 배열의 특정 인덱스 값을 확인한다.
  • p &number[0]: 배열 각 요소의 메모리 주소를 확인한다.

 

메모리 직접 조사

  • x/xw [주소]: 특정 메모리 주소의 값을 16진수(x) 워드 단위(w)로 출력한다.

  • x/5xw number: number 주소부터 5개의 워드 데이터를 16진수로 출력한다.

 

3. 메모리 구조 분석 결과

GDB 분석을 통해 확인한 핵심 사항은 다음과 같다.

배열의 연속성

&number[0]부터 &number[4]까지의 주소를 확인하면 값이 4바이트(int 크기)씩 일정하게 증가하는 것을 알 수 있다.

이는 배열이 메모리 상에 연속적으로 배치됨을 의미한다.

 

배열 이름의 의미

x/xw number 명령 실행 시 배열의 첫 번째 요소 주소인 0x7fffffffdd20과 동일한 곳을 가리킨다.

즉, 배열의 이름은 배열의 시작 주소를 의미한다.

연산자 우선순위

&number[0] 연산 시, 대괄호([]) 연산자가 주소(&) 연산자보다 우선순위가 높다.

따라서 number[0] 요소를 먼저 찾고, 그 요소의 주소를 추출하게 된다.

 

 

4. 정리

  • p 명령어로 변수 값을, x 명령어로 메모리 주소의 실제 데이터를 확인할 수 있다.
  • 배열은 메모리의 연속된 공간을 점유하며, 인덱스가 증가할 때마다 자료형의 크기만큼 주소가 증가한다.
  • 배열명 자체가 시작 주소이므로 포인터 연산을 통해 효율적인 데이터 제어가 가능하다.