Reputation: 2573
A project I'm working on and some MSDN documentation has code such as this:
IFileOpenDialog *pFileOpen;
IID_PPV_ARGS(&pFileOpen)
Where IID_PPV_ARGS is:
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)
My question is about the **(ppType)
part. Wouldn't this end up dereferencing a null or unitialized pointer? Why does this work?
Upvotes: 4
Views: 2747
Reputation: 21
One more point for Jonathan's answer (as I cannot leave a comment due to my reputation is too low):
In the debug build, __uuidof
always initializes an object dynamically (at runtime). In a release build, __uuidof can statically (at compile time) initialize an object.
See: https://learn.microsoft.com/en-us/cpp/cpp/uuidof-operator?view=msvc-160
Upvotes: 2
Reputation: 37192
__uuidof()
is a proprietary Microsoft extension, that the compiler knows how to deal with. It's evaluated at compile time, not at run time.
The compiler attempts to look up and substitute the UUID for the given interface. The interface declares its UUID using the __declspec(uuid("..."))
extension. If the compiler can't find the UUID, the build will fail. No pointers are actually dereferenced at run time.
ppType
is set to a IFileOpenDialog**
, thus *(ppType)
is a IFileOpenDialog*
and **(ppType)
is a IFileOpenDialog
. As such, __uuidof(**(ppType))
is evaluated as __uuidof(IFileOpenDialog)
at compile time.
It's the same as doing this:
char* ptr = nullptr;
size_t charSize = sizeof(*ptr);
sizeof(*ptr)
will be evaluated as sizeof(char)
at compile time, even though ptr
is null.
Upvotes: 11