[1. 개요]
Segmentation fault 와 관련하여 고민한 내용 정리
[2. 상황]
특정 함수 진입 시, c++ 로 작성한 애플리케이션이 segmentation fault 발생과 함께 죽는 현상.
gdb 로 디버깅 시, 함수 진입 만 하였는데, segmentation fault 가 발생.
의심이 것 중 하나는 스택 오버플로우..
[3. 예제]
1 #include <iostream>
2
3
4 void myfunc()
5 {
6 char arr[MYSZ * 1024 * 1024];
7 std::cout << "arr size is " << sizeof(arr) << std::endl;
8 }
9
10 int main()
11 {
12 std::cout << "main start" << std::endl;
13 myfunc();
14 return 0;
15 }
ulimit -s 가 8192 (8 Mbyte 인 경우)
- g++ main.cpp -g -DMYSZ=9
- g++ main.cpp -Wl,-z,stack-size=10485760 -g -DMYSZ=9
위 두가지 모두 segmentation fault 가 발생
ulmit -s 16384 로 수정 (16 Mbyte 인 경우)
- g++ main.cpp -g -DMYSZ=9
- g++ main.cpp -Wl,-z,stack-size=10485760 -g -DMYSZ=9
위 두가지 모두 정상 종료 확인.
즉, 컴파일 시 링커에 명시하는 스택 크기보다, ulimit 값에 더 의존적임.
[3. 스레드 스택]
#include <iostream>
#include <pthread.h>
int main()
{
std::cout << "main start" << std::endl;
pthread_attr_t attr;
void* stack_addr;
size_t stack_size;
pthread_getattr_np(pthread_self(), &attr);
pthread_attr_getstack(&attr, &stack_addr, &stack_size);
std::cout << "Stack addr " << stack_addr << std::endl;
std::cout << "Stack size " << stack_size << std::endl;
return 0;
}
위 코드 역시, 스택의 크기는 ulimit 값에 따라 바뀌 었음.
[4. 결론. (chatgpt)]
ulimit -s | 전체 프로세스의 일괄 적용 | 각 스레드 실행 시 기본 스택 |
-Wl,-z,stack-size | 실행 파일 | ELF 헤더에 스택 크기 저장 |
pthread_attr_setstack | 프로세스 내 스레드 | 특정 스레드의 스택 크기 지정 |
즉, pthread_attr_setstack 등으로 스택 크기를 명시하지 않으면
- ulimit -s 에 의해 명시된 스택 크기를 스레드가 사용하게 된다.
- 개별 스택 크기는 ulimit -s 값 이하로만 설정 가능.
문제는 실제 사용하는 스택 메모리가 예상 한 것보다 더 많이 사용할 수 있다.
- 재귀 함수 호출.
- 큰 지역 변수 사용 (매우 긴 배열..)
- ...
런타임 중, 스레드의 스택 오버플로우 발생 가능성이 있음.
=> pthread를 사용하면, 리눅스 커널이 자동으로 각 스레드의 스택 끝에 읽기/쓰기가 불가능한 페이지를 추가함.
=> 이 덕분에, 스택이 넘쳐도 다른 스레드의 영역을 침범하지 않고 바로 프로그램이 크래시됨.
=> pthread_attr_setguardsize(&attr, 0); // 가드 페이지 제거 한다면?
'서버 관리 > 리눅스' 카테고리의 다른 글
multibyte string to widechar string (0) | 2025.01.22 |
---|---|
file 명령어 (0) | 2025.01.21 |
journalctl 로그 파일 관리 (디스크 확보를 위한) (0) | 2024.06.11 |
chrome 임시 파일 관련 용량 관리 (0) | 2024.06.11 |
계정 추가. useradd, adduser (1) | 2023.10.17 |