__stdcall의 의미와 사용법은 무엇입니까?
__stdcall
요즘 많이 보았습니다 .
MSDN은 그것이 실제로 무엇을 의미하는지, 언제, 왜 사용 해야하는지 명확하게 설명하지 않습니다.
누군가가 예를 들어 한두 가지 설명을 해주면 감사하겠습니다.
C / C ++의 모든 함수에는 특정 호출 규칙이 있습니다. 호출 규칙의 요점은 호출자와 호출 수신자간에 데이터가 전달되는 방법과 호출 스택 정리와 같은 작업을 담당하는 사람을 설정하는 것입니다.
Windows에서 가장 많이 사용되는 호출 규칙은 다음과 같습니다.
__stdcall
, 스택에 매개 변수를 역순으로 푸시합니다 (오른쪽에서 왼쪽으로)__cdecl
, 스택에 매개 변수를 역순으로 푸시합니다 (오른쪽에서 왼쪽으로)__clrcall
, 매개 변수를 CLR 식 스택에 순서대로로드합니다 (왼쪽에서 오른쪽으로).__fastcall
, 레지스터에 저장된 후 스택에 푸시 됨__thiscall
, 스택에 푸시; ECX에 저장된이 포인터
이 지정자를 함수 선언에 추가하면 기본적으로이 특정 함수가이 특정 호출 규칙을 갖도록 컴파일러에 알립니다.
호출 규칙은 여기에 설명되어 있습니다.
Raymond Chen은 여기에서 시작하는 다양한 호출 규칙 (5 부)의 역사에 대한 긴 시리즈도했습니다.
전통적으로 C 함수 호출은 호출자가 일부 매개 변수를 스택에 푸시하고 함수를 호출 한 다음 스택을 팝하여 푸시 된 인수를 정리하는 방식으로 이루어집니다.
/* example of __cdecl */
push arg1
push arg2
push arg3
call function
add sp,12 // effectively "pop; pop; pop"
참고 : 위에 표시된 기본 규칙은 __cdecl입니다.
가장 많이 사용되는 다른 규칙은 __stdcall입니다. 그 안에서 매개 변수는 호출자에 의해 다시 푸시되지만 스택은 호출자에 의해 정리됩니다. Win32 API 함수 (의 WINAPI 매크로에 의해 정의 됨)에 대한 표준 규칙이며 "Pascal"호출 규칙이라고도합니다.
/* example of __stdcall */
push arg1
push arg2
push arg3
call function // no stack cleanup - callee does this
이것은 사소한 기술적 세부 사항처럼 보이지만 호출자와 호출 수신자간에 스택을 관리하는 방법에 불일치가있는 경우 스택은 복구 될 가능성이없는 방식으로 파괴됩니다. __stdcall이 스택 정리를 수행하기 때문에이 작업을 수행하는 (매우 작은) 코드는 __cdecl에서와 같이 모든 호출자에서 복제되는 것이 아니라 한 곳에서만 발견됩니다. 크기 영향은 큰 프로그램에서만 볼 수 있지만 이로 인해 코드가 매우 약간 작아집니다.
printf ()와 같은 가변 함수는 __stdcall을 제대로 처리하기가 거의 불가능합니다. 왜냐하면 호출자 만이 그들을 정리하기 위해 얼마나 많은 인수가 전달되었는지 실제로 알고 있기 때문입니다. 피 호출자는 몇 가지 좋은 추측을 할 수 있지만 (예 : 형식 문자열을 살펴봄으로써) 스택 정리는 호출 규칙 메커니즘 자체가 아니라 함수의 실제 논리에 의해 결정되어야합니다. 따라서 __cdecl 만 가변 함수를 지원하므로 호출자가 정리를 수행 할 수 있습니다.
링커 기호 이름 장식 : 위의 글 머리 기호에서 언급했듯이 "잘못된"규칙을 사용하여 함수를 호출하는 것은 재앙이 될 수 있으므로 Microsoft는이를 방지 할 수있는 메커니즘을 가지고 있습니다. 잘 작동하지만 이유가 무엇인지 모를 경우 화를 낼 수 있습니다. 그들은 호출 규칙을 추가 문자 (종종 "장식"이라고 함)가있는 저수준 함수 이름으로 인코딩하여이 문제를 해결하기로 결정했으며 링커에서 관련없는 이름으로 처리합니다. 기본 호출 규칙은 __cdecl이지만 각 규칙은 / G?를 사용하여 명시 적으로 요청할 수 있습니다. 매개 변수를 컴파일러에 전달합니다.
__cdecl (cl / Gd ...)
이 유형의 모든 함수 이름은 밑줄로 시작되며 호출자가 스택 설정 및 스택 정리를 담당하므로 매개 변수 수는 실제로 중요하지 않습니다. 호출자와 호출 수신자가 실제로 전달 된 매개 변수 수에 대해 혼동 될 수 있지만 적어도 스택 원칙은 적절하게 유지됩니다.
__stdcall (cl / Gz ...)
이러한 함수 이름은 밑줄로 시작하고 전달 된 매개 변수의 바이트 수와 함께 @가 추가됩니다. 이 메커니즘에 의해 "잘못된"유형 또는 잘못된 매개 변수 수로 함수를 호출 할 수 없습니다.
__fastcall (cl / Gr ...)
이러한 함수 이름은 @ 기호로 시작하고 __stdcall과 같이 @parameter 개수가 접미사로 붙습니다.
예 :
Declaration -----------------------> decorated name
void __cdecl foo(void); -----------------------> _foo
void __cdecl foo(int a); -----------------------> _foo
void __cdecl foo(int a, int b); -----------------------> _foo
void __stdcall foo(void); -----------------------> _foo@0
void __stdcall foo(int a); -----------------------> _foo@4
void __stdcall foo(int a, int b); -----------------------> _foo@8
void __fastcall foo(void); -----------------------> @foo@0
void __fastcall foo(int a); -----------------------> @foo@4
void __fastcall foo(int a, int b); -----------------------> @foo@8
__stdcall is a calling convention: a way of determining how parameters are passed to a function (on the stack or in registers) and who is responsible for cleaning up after the function returns (the caller or the callee).
Raymond Chen wrote a blog about the major x86 calling conventions, and there's a nice CodeProject article too.
For the most part, you shouldn't have to worry about them. The only case in which you should is if you're calling a library function that uses something other than the default -- otherwise the compiler will generate the wrong code and your program will probably crash.
Unfortunately, there is no easy answer for when to use it and when not.
__stdcall means that the arguments to a function are pushed onto the stack from the first to the last. This is as opposed to __cdecl, which means that the arguments are pushed from last to first, and __fastcall, which places the first four (I think) arguments in registers, and the rest go on the stack.
You just need to know what the callee expects, or if you are writing a library, what your callers are likely expect, and make sure you document your chosen convention.
It specifies a calling convention for a function. A calling convention is a set of rules how parameters are passed to a function: in which order, per address or per copy, who is to clean up the parameters (caller or callee) etc.
__stdcall denotes a calling convention (see this PDF for some details). This means it specifies how function arguments are pushed and popped from the stack, and who is responsible.
__stdcall is just one of several calling conventions, and is used throughout the WINAPI. You must use it if you provide function pointers as callbacks for some of those functions. In general, you do not need to denote any specific calling convention in your code, but just use the compiler's default, except for the case noted above (providing callbacks to 3rd party code).
That's a calling convention that WinAPI functions need to be called properly. A calling convention is a set of rules on how the parameters are passed into the function and how the return value is passed from the function.
If the caller and the called code use different conventions you run into undefined behaviour (like such a strange-looking crash).
C++ compilers don't use __stdcall by default - they use other conventions. So in order to call WinAPI functions from C++ you need to specify that they use __stdcall - this is usually done in Windoes SDK header files and you also do it when declaring function pointers.
simply put when you call function, it gets loaded in stack/register. __stdcall is one convention/way(right argument first, then left argument ...), __decl is another convention that are used to load the function on the stack or registers.
If you use them you instruct the computer to use that specific way to load/unload the function during linking and hence you would not get a mismatch/crash.
Otherwise the function-callee and function-caller might use different conventions causing program to crash.
__stdcall is the calling convention used for the function. This tells the compiler the rules that apply for setting up the stack, pushing arguments and getting a return value. There are a number of other calling conventions like __cdecl, __thiscall, __fastcall and __naked.
__stdcall is the standard calling convention for Win32 system calls.
More details can be found on Wikipedia.
참고URL : https://stackoverflow.com/questions/1306414/what-is-the-meaning-and-usage-of-stdcall
'developer tip' 카테고리의 다른 글
레일스 rspec 전과 각 전 (0) | 2020.11.01 |
---|---|
여러 인스턴스에 jQuery datepicker 적용 (0) | 2020.11.01 |
$ (ProjectDir)의 값을 어떻게 알 수 있습니까? (0) | 2020.11.01 |
jQuery는 div를 특정 인덱스로 삽입 (0) | 2020.11.01 |
내가 화면에 있는지 어떻게 알 수 있습니까? (0) | 2020.11.01 |