본문 바로가기

분류대기

Segmentation fault 사례

[1. 개요]

C++ 코드 작성 시, 발생한 segmentation fault 사례 및 해결 방안 정리


[2. 예제]

#include <iostream>
#include <string>
#include <deque>
#include <cstring>

struct MyStruct {
    long long a;
    int b;
    char c[32];
    std::string d;
};

std::deque<MyStruct> dq;

void GetAndErase(MyStruct& ref)
{
    if (dq.size() > 0) {
        ref = dq.back(); // seg fault 가 발생하는 순간.
        dq.pop_back();
    }
}

int main()
{
    {
        MyStruct item;
        strcpy(item.c, "Hello_World");

        dq.push_front(item);
    }

    MyStruct elem;
    memset(&elem, 0, sizeof(elem));

    GetAndErase(elem);

    std::cout << elem.c << std::endl;
    std::cout << elem.d << std::endl;

    return 0;
}

 

일단, 문제의 원인은 구조체 elem 의 초기화 에 있다.

  • 구조체 MyStruct 는 마지막 멤버가 std::string 객체이다.
  • std::string 의 내부 멤버 변수는 어떻게 되는지 알 수 없지만, 어떤 포인터 변수가 있으리라 생각 할 수 있다.
  • memset 으로 인해, 이 포인터 변수는 0으로 초기화 된다. (nullptr 이 되버리는 것으로 볼 수 있나?)
  • 이제, dq.back() 을 통해 std::string 을 복사 할 때 문제가 될 것으로 본다. (얕은 or 깊은 복사 ? )
  • 위 예제의 exception 은 msvc 컴파일러에서 빌드한 경우 발생하지 않았다.
  • 그 외, GNU 컴파일러에서만 발생하는 듯. 

실제로 위 예제에서 memset 를 주석처리하면 exception 이 발생하지 않는다.

 

또, 아래 예제에서도 exception 이 발생하지 않는다.

  • memset 를 사용하였음.
  • 멤버 변수 d 의 초기화가 발생하였음.
  • 정확한 원인은?
#include <iostream>
#include <string>
#include <deque>
#include <cstring>

struct MyStruct {
    long long a;
    int b;
    char c[32];
    std::string d;
};

std::deque<MyStruct> dq;

void GetAndErase(MyStruct& ref)
{
    if (dq.size() > 0) {
        ref = dq.back();
        dq.pop_back();
    }
}

int main()
{
    {
        MyStruct item;
        strcpy(item.c, "Hello_World");
        item.d = "New_World"; // 문자열 초기화.
    
        dq.push_front(item);
    }
    
    MyStruct elem;
    memset(&elem, 0, sizeof(elem));

    GetAndErase(elem);

    std::cout << elem.c << std::endl;
    std::cout << elem.d << std::endl;

    return 0;
}

[3. 결론]

class 나 struct 를 대상으로 memset 의 사용은 다소 위험할 수 있다.

  • 내부 멤버 변수가 모두 primitive 한 자료형으로 되어있는 경우라면 상관 없지만...
  • 가급적 초기화 함수 등을 정의하여 사용하도록 하는 편이 좋아 보임.

 

'분류대기' 카테고리의 다른 글

Socket, 멀티 캐스트 & 브로드 캐스트  (0) 2025.03.09
Segmentation fault 해결 (C++)  (0) 2025.03.04
윈도우 컴파일 에러. [No Target Architecture]  (0) 2025.03.04
소켓 Linger 옵션  (0) 2025.02.26
[인코딩] EUCKR  (0) 2025.02.04