본문 바로가기
프로그래밍/C, C++

C 구조체 사용 시 포인터 저장 문제

by argentdarae 2025. 4. 9.
반응형

파일에 구조체 데이터를 저장할 때 포인터를 사용하면 에러가 발생할 수 있다

해당 포인터가 가리키는 영역은 파일에 직접 저장되지 않기 때문이다

 

또한 디스크에 저장된 포인터는 다음에 로드했을 때 유효하지 않은 주소이다

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

typedef struct {
    char *name;  // 문자열을 동적 할당 받아 저장할 포인터
    int  age;
} PersonPtr_t;

int main(void) 
{
    const char *filename = "person_ptr.bin";
    PersonPtr_t p1;
    FILE *fp;

    /* 1. 구조체의 포인터 멤버에 동적 할당 문자열 저장 */
    p1.age = 25;
    p1.name = (char *)malloc(10);
    strcpy(p1.name, "Alice");

    /* 2. 파일에 저장 (포인터 주소만 저장됨) */
    fp = fopen(filename, "wb");
    if (!fp) {
        perror("File open error");
        return 1;
    }
    fwrite(&p1, sizeof(PersonPtr_t), 1, fp);
    fclose(fp);

    /* 동적 할당 해제 */
    free(p1.name);

    /* 3. 파일에서 다시 읽기 */
    PersonPtr_t p2;
    fp = fopen(filename, "rb");
    if (!fp) {
        perror("File open error");
        return 1;
    }
    fread(&p2, sizeof(PersonPtr_t), 1, fp);
    fclose(fp);

    /*
     * 문제 상황:
     * p2.name에는 파일에 저장된 '포인터 값'이 들어 있음.
     * 그러나 이 주소는 현재 프로그램의 유효 메모리가 아님.
     * 즉, p2.name로 접근 시 잘못된 주소로 접근하게 됨.
     */
    printf("p2.age = %d\n", p2.age);
    printf("p2.name = %s\n", p2.name);

    return 0;
}


================ 실행 결과 ================
p2.age = 25
p2.name =

 

이러한 문제를 피하려면, 실제 데이터를 구조체 자체에 복사해 두는 방식으로 진행해야 한다

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

#define NAME_SIZE 32

typedef struct {
    char name[NAME_SIZE];  // 고정 길이 배열로 직접 문자열을 저장
    int  age;
} PersonDeep_t;

int main(void) 
{
    const char *filename = "person_deep.bin";
    PersonDeep_t p1;
    FILE *fp;

    /* 1. 구조체 내부 배열에 직접 문자열 복사 (깊은 복사) */
    p1.age = 30;
    /* strcpy로 p1.name 배열에 문자열을 직접 복사 */
    strcpy(p1.name, "Bob");

    /* 2. 파일에 저장 (문자열 데이터 자체가 구조체에 포함) */
    fp = fopen(filename, "wb");
    if (!fp) {
        perror("File open error");
        return 1;
    }
    fwrite(&p1, sizeof(PersonDeep_t), 1, fp);
    fclose(fp);

    /* 3. 파일에서 다시 읽기 */
    PersonDeep_t p2;
    fp = fopen(filename, "rb");
    if (!fp) {
        perror("File open error");
        return 1;
    }
    fread(&p2, sizeof(PersonDeep_t), 1, fp);
    fclose(fp);

    /* 정상 작동: p2.name 내부에 문자 배열이 이미 복사되어 있음 */
    printf("p2.age = %d\n", p2.age);
    printf("p2.name = %s\n", p2.name);

    return 0;
}


================ 실행 결과 ================
p2.age = 30
p2.name = Bob

Reference

struct (C programming language) - Wikipedia

'프로그래밍 > C, C++' 카테고리의 다른 글

C 언어 공용체 (union)  (0) 2025.04.10
C 구조체와 비트 플래그  (0) 2025.04.10
C 언어의 구조체  (0) 2025.04.09
C 언어 파일 탐색  (0) 2025.04.09
C의 파일 오류 처리  (0) 2025.04.09