2013-02-07 3 views
3

나는 sigaltstack에 대한 대안 스택을 설정하기 위해 적어도 세 가지 다른 접근법을 보았다. 나는 하나가 가장 좋은 방법이다 궁금 해요 :sigaltstack을 올바르게 설정하는 방법은 무엇입니까?

접근 # 1

stack_t sigstk; 
sigstk.ss_size = 0; 
sigstk.ss_flags = 0; 
sigstk.ss_sp = mmap (NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); 
if (sigstk.ss_sp != MAP_FAILED) { 
    sigstk.ss_size = SIGSTKSZ; 
    if (sigaltstack (&sigstk, 0) < 0) { 
     sigstk.ss_size = 0; 
     printf ("sigaltstack errno=%d\n", errno); 
    } 
} else { 
    printf ("malloc (SIGSTKSZ) failed!\n"); 
} 

접근 # 2 (우리는 잠시 동안을 사용하고 있지만, 여기에 할당 된 메모리가 누수 탐지에 표시 합니다 ('누출'명령))

stack_t sigstk; 
sigstk.ss_size = 0; 
sigstk.ss_flags = 0; 
sigstk.ss_sp = malloc (SIGSTKSZ); 
if (sigstk.ss_sp != NULL) { 
    sigstk.ss_size = SIGSTKSZ; 
    if (sigaltstack (&sigstk, 0) < 0) { 
     sigstk.ss_size = 0; 
     free (sigstk.ss_sp); 
     printf ("sigaltstack errno=%d\n", errno); 
    } 
} else { 
    printf ("malloc (SIGSTKSZ) failed!\n"); 
} 

접근 # 3

stack_t sigstk; 
static char ssp[SIGSTKSZ]; 
sigstk.ss_size = SIGSTKSZ; 
sigstk.ss_flags = 0; 
sigstk.ss_sp = ssp; 
sigstk.ss_size = SIGSTKSZ; 
if (sigaltstack (&sigstk, 0) < 0) { 
    sigstk.ss_size = 0; 
    free (sigstk.ss_sp); 
    printf ("sigaltstack errno=%d\n", errno); 
} 

감사합니다 , Ákos (Mac OS X 10.8.2)

답변

1

저는 sigaltstack()에 익숙하지 않지만, the man page을 검토했습니다. 귀하의 3 가지 접근 방식의 차이점은 ss_sp 구조체 구성원에 대해 공간을 할당하는 방법에있는 것 같습니다. mmap()을 사용하고, 전통적으로 malloc()을 사용하거나 스택에서 할당하십시오.

시스템을 올바르게 이해하고 있다면 은 스택에서 할당하기를 원합니다. 기능을 종료 한 후, 스택 공간은 즉시 재사용되고 용도가 변경 (즉, 변경)되며, sigaltstack()의 기능이 중단됩니다.

전통적인 malloc()을 추천합니다. 구문이 마음에 들면 mmap()으로 갈 수 있습니다. 내 이해에 따라 mmap()NULL 주소를 전달하면 어쨌든 malloc()과 같습니다.

+1

제 3의 접근법에서 '정적'스토리지 클래스 지정자는 변수가 범위를 벗어나는 것을 허용하지 않습니다. –

+0

아, 정적 규정자를 알지 못했습니다. 명확히 해 주셔서 감사합니다. 이 경우 모든 접근법이 다소 유효하고 개인적인 취향에 달려 있습니다. 아니면 특정 접근법에 특정 문제가 있습니까? –

+0

예.우리는 현재 두 번째 방법을 사용하고 있지만, malloc 된 메모리가 누수 탐지에 나타납니다. –

2

접근 방식 # 1이 가장 좋습니다. 이유는 위치 때문입니다. 가정 당신은 # 2를 사용하여 코드의 흐름은 다음과 같이 진행됩니다

void *blah = malloc (...) 
... 
stack_t sigstk; 
sigstk.ss_size = 0; 
sigstk.ss_flags = 0; 
sigstk.ss_sp = malloc (SIGSTKSZ); 

당신이 당신의 신호 처리기에서 스택 공간을 소모하면 이제 어떻게됩니까? 스택이 아래쪽으로 늘어나고 blah이 가리키는 메모리를 방해합니다. 어딘가에 약간의 재귀가 있으면 쉽게 발생할 수 있습니다. # 3은 같은 종류의 문제가 있습니다.

대신, 사용의 mmap은 멀리 데이터 힙에서 다른 풀에서 할당하기 때문에, 설치 가드 페이지에 대한 좋은 생각이다 :

이제
char* mem = mmap (NULL, 
        SIGSTKSZ + 2*getpagesize(), 
        PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 
        -1, 0); 
mprotect(mem, getpagesize(), PROT_NONE); 
mprotect(mem + getpagesize() + SIGSTKSZ, getpagesize(), PROT_NONE); 
sigstk.ss_sp = mem + getpagesize(); 
... 

당신이 얻을거야 SIGSEGV 경우 스택 오버플로가 발생하여 임의의 메모리 덮어 쓰기보다 디버깅이 약 10 억 배 더 쉽습니다. :)

# 2가 누수로 계산 된 이유는 거짓 긍정 일 가능성이 높습니다. 사용중인 누수 도구가 malloc이 아닌이 작업에 mmap을 사용하는 것을 선호하는 또 다른 이유 인 자체 변형을 사용하여 malloc 라이브러리 함수를 무시합니다.

관련 문제