Could an implicit compiler created default constructor have more than a null body? According to IBM's website, the answer is: no.
I have this project that's kind of stumping me though:
This is where an instance of a class called StackWalkerToConsole with no defined default constructor gets declared:
void func5()
{
StackWalkerToConsole sw;
...
}
This somehow causes one of the user-defined constructors of its parent class to get called:
StackWalker::StackWalker(int options, LPCSTR szSymPath, DWORD dwProcessId, HANDLE hProcess)
{
// The function has a body, I just removed it for clarity's sake.
...
}
So I put a breakpoint on this constructor, and using the callstack I looked at the default constructor for StackWalkerToConsole. Since it's not defined in the source code, I could only look at its dissassembly:
StackWalker_VC2017.exe!StackWalkerToConsole::StackWalkerToConsole(void):
0000000140008210 mov qword ptr [rsp+8],rcx
0000000140008215 push rdi
0000000140008216 sub rsp,40h
000000014000821A call qword ptr [__imp_GetCurrentProcess (014012E060h)]
0000000140008220 mov qword ptr [rsp+30h],rax
0000000140008225 call qword ptr [__imp_GetCurrentProcessId (014012E068h)]
000000014000822B mov rcx,qword ptr [rsp+30h]
0000000140008230 mov qword ptr [rsp+20h],rcx
0000000140008235 mov r9d,eax
0000000140008238 xor r8d,r8d
000000014000823B mov edx,3Fh
0000000140008240 mov rcx,qword ptr [this]
0000000140008245 call StackWalker::StackWalker (0140002F1Dh)
000000014000824A mov rax,qword ptr [this]
000000014000824F lea rcx,[StackWalkerToConsole::`vftable' (01400ED6C0h)]
0000000140008256 mov qword ptr [rax],rcx
0000000140008259 mov rax,qword ptr [this]
000000014000825E add rsp,40h
0000000140008262 pop rdi
This compiler defined constructor is calling 2 WinApi functions: GetCurrentProcess and GetCurrentProcessId and calling the user-defined constructor for StackWalker.
Does anyone know why this is? I should mention, the parent class StackWalker does not have any user defined default constructors either.
If further information is required I'd be glad to supply it. Thank you for reading this far.
Edit: This is the github for the code: It's a tiny project, just 1 cpp file and 1 main.cpp file to test it. I'm assuming no one has the time and energy to go through the code, but putting it in here just in case.
In the post I'm referencing Line 41 from main.cpp and Line 929 from StackWalker.cpp
The class you've referenced:
class StackWalkerToConsole : public StackWalker
{
protected:
virtual void OnOutput(LPCSTR szText) { printf("%s", szText); }
};
Has an implicitly-declared default constructor that looks similar to this:
StackWalkerToConsole::StackWalkerToConsole() : StackWalker() {}
Which calls this constructor of StackWalker:
StackWalker(int options = OptionsAll,
LPCSTR szSymPath = NULL,
DWORD dwProcessId = GetCurrentProcessId(),
HANDLE hProcess = GetCurrentProcess());
(StackWalker
does have a user-defined default constructor, it's this one that can be called with zero arguments)
So while there's no body of StackWalkerToConsole
's default constructor, its base class is initialized using the default arguments StackWalker(OptionsAll, NULL, GetCurrentProcessId(), GetCurrentProcess())
and the body of the StackWalker constructor is run.