스택 메모리를 사용하지 않을 때 왜 할당됩니까?


14

다음 예제를 고려하십시오.

struct vector {
    int  size() const;
    bool empty() const;
};

bool vector::empty() const
{
    return size() == 0;
}

생성 된 어셈블리 코드 vector::empty(최적화와 함께 clang) :

push    rax
call    vector::size() const
test    eax, eax
sete    al
pop     rcx
ret

왜 스택 공간을 할당합니까? 전혀 사용되지 않습니다. pushpop생략 할 수있다. 최적화 된 MSVC 및 gcc 빌드는이 기능에 대해 스택 공간을 사용 하므로 ( godbolt 참조 ) 이유가 있어야합니다.


7
암시 적 this매개 변수 를 설명했습니까 ?
dan04

1
@ 밥 __ : 아니요. 왜 내가해야합니까? vector::size()이 예제에서는 인라인되지 않은 것을 시뮬레이션하기 위해 정의되지 않았습니다.
Dr. Gut

1
그렇다면 어떻게 컴파일러가 모르는 것을 최적화 할 수 있을까요?
Bob__

1
@Bob__ :의 구현을 아는 것은에 vector::size()대한 스택 프레임 할당 또는 할당과 관련이 없다고 생각 합니다 vector::empty(). 에서 empty()가 방금 전화, 그것은 무엇이든.
Dr. Gut

1
글쎄, 당신은 무언가 를 반환 하는 함수를 호출하고 있습니다 . 더 잘 알지 못하면 공간이 필요합니다.
Bob__

답변:


11

스택 공간을 할당하므로 스택은 16 바이트로 정렬됩니다. 리턴 주소는 8 바이트가 걸리므로 스택을 16 바이트로 정렬하려면 추가 8 바이트 공간이 필요합니다.

스택 프레임의 정렬은 일부 컴파일러의 명령 행 인수로 구성 할 수 있습니다.

  • MSVC : 설명서 에는 스택이 항상 16 바이트로 정렬되어 있다고 나와 있습니다. 어떤 명령 줄 인수 도이를 변경할 수 없습니다 . godbolt 예제는 rsp함수의 시작 부분 에서 40 바이트를 빼는 것을 보여줍니다 . 이는 다른 것도 이것에 영향을 미칩니다.
  • clang :이 -mstack-alignment옵션은 스택 정렬을 지정합니다. 문서화되지는 않았지만 기본값은 16 인 것 같습니다. 8로 설정하면 스택 할당 ( pushpop)이 생성 된 어셈블리 코드에서 사라집니다.
  • gcc :이 -mpreferred-stack-boundary옵션은 스택 정렬을 지정합니다. 주어진 값이 N이면 2 ^ N 바이트의 정렬을 의미합니다. 기본값은 4이며 16 바이트를 의미합니다. 3 (즉, 8 바이트)으로 설정하면 스택 할당 ( subaddfor rsp)이 생성 된 어셈블리 코드에서 사라집니다.

godbolt를 확인하십시오 .


즉, C ++ 전문가가 전문가가 항상 경고하고 이유의 : 제대로 효율적인 것 작은 ...에만이 방식이 가장 긴 / 가장 큰 크기의 순서로 넣어 구조체 / 클래스 멤버
nonock

@geza : 감사합니다. 다른 두 컴파일러에 대한 조사를 수행하여 답변에 썼습니다. 당신은 그것을 좋아합니까?
Dr. Gut

1
@ Dr.Gut : 감사합니다. 대답이 훨씬 좋고 완전했습니다. 스택 정렬은 일반적으로 시스템의 ABI에 문서화되어 있습니다 (예 : 일부 시스템의 경우 다음 문서가 있습니다 : github.com/hjl-tools/x86-psABI/wiki/X86-psABI ).
geza

@geza : 감사합니다.
Dr. Gut
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.