2014-09-07 5 views
1

나는 -O3 -x c -std=c99 -fno-builtin -nostdlib -ffreestandinggcc가 재귀 호출을하고 있습니까?

unsigned char *memset(unsigned char *dest, unsigned char val, int count) 
{ 
    unsigned char* p = dest; 
    while (count--) 
     *p++ = val; 

    return dest; 
} 

#include <stdio.h> 

int main() 
{ 
    unsigned char c[20]; 
    memset(c, 'a', 19); 
    c[19] = '\0'; 
    printf((const char*) c); 
} 

이 코드를 컴파일하고 memset GCC 어셈블리 출력에 호출 무엇 검사 godbolt을 사용하고 있습니다. 플래그와

memset: 
    test edx, edx 
    je .L6 
    sub edx, 1 
    sub rsp, 8 
    movzx esi, sil 
    add rdx, 1 
    call memset 
    add rsp, 8 
    ret 
.L6: 
    mov rax, rdi 
    ret 
main: 
    sub rsp, 40 
    movabs rax, 7016996765293437281 
    mov QWORD PTR [rsp], rax 
    mov QWORD PTR [rsp+8], rax 
    mov eax, 24929 
    mov WORD PTR [rsp+16], ax 
    mov rdi, rsp 
    xor eax, eax 
    mov BYTE PTR [rsp+18], 97 
    mov BYTE PTR [rsp+19], 0 
    call printf 
    add rsp, 40 
    ret 

은 내가 GCC는 *p++ = val;에서 재귀 호출을하고있다처럼 내장 memset과 색상 화 godbolt 사용에서 판단 보이는 통화 그것의 모든 가능성을 제거하려고 시도하고있어 사용. 그래서 그것은 재귀 또는 내장 호출을하고 있습니까 memset?

+1

gdb를 사용하여 어떤 memset이 호출 중인지 확인할 수 있습니까? –

+1

함수의 이름을 변경하고'memset' (내장 함수를 의미) 또는 새로운 이름을 호출하는지 확인하십시오. – interjay

+0

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56888 –

답변

1

다른 사람이 지적했듯이 배열 c 요소의 설정이 인라인되었습니다. 결과적으로 구현 한 memset()도 호출되지 않습니다. 이것은 -03 컴파일러 옵션의 사용 결과입니다. 컴파일러는 최적화에있어 매우 공격적입니다. 또한 실행 경로에는 재귀가 없습니다.

그러나 이는 사용자의 질문에 완전히 대답하지 않습니다. 디스 어셈블 된 출력에 표시된 memset()은 실제로 내장 버전이 아니며 실행되지도 않습니다.

덧붙여서 -freestanding 플래그가 자동으로 의미하므로 -fno-builtin 플래그를 적용 할 필요가 없습니다. 또한 가비지 수집을 사용 가능하게하면, 디스 어셈블 된 출력의 memset() 루틴이 사라지는 것을 알게 될 것입니다.

+0

그 이유는 '정적'이 아니므로 다른 모듈이 호출 될 가능성이 있기 때문입니다. 컴파일러 플래그를 고려할 때, 그것은 깨진 코드입니다. gcc explorer에 따르면, 버그는'g ++ v4.8'에서 나타 났고, 이전 버전과'clang'은 정상적으로 작동합니다. – Jester

관련 문제