HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

CRAIICall class

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
craiicallclassstackoverflow

Problem

I thought it was a good idea to use this in my C++ projects:

class CRAIICall
{
public:
    typedef void (WINAPI * FnType)(HANDLE);

    CRAIICall(HANDLE h, FnType fun)
    : m_h(h), m_fun(fun) 
    {}

    ~CRAIICall() { 
        if (m_h) { m_fun(m_h); }
    }

private:
    HANDLE m_h;
    FnType m_fun;
};


and use it like this in a function:

HMODULE hSrClient = ::LoadLibraryW(L"srclient.dll");
CRAIICall(hSrClient, (CRAIICall::FnType)::FreeLibrary);


so that I can simply return from my function at any point, or throw exceptions.

Is it safe to cast a function pointer like this?

Solution

No it is not safe (It is undefined behavior):

The called function may put stuff on the stack (or somewhere else) as the return value. Expecting the caller to deal with it at their end. If the caller does not deal with the return value appropriately then you have undefined behavior (the returned object may have a destructor that needs to be called for example).

This line is probably not doing what you expect:

CRAIICall(hSrClient, (CRAIICall::FnType)::FreeLibrary);


This is creating a temporary object. Which goes out of scope at the end of the expression (the semicolon in this case). And thus the temporary objects destructor is getting called just after the constructor completes.

Code Snippets

CRAIICall(hSrClient, (CRAIICall::FnType)::FreeLibrary);

Context

StackExchange Code Review Q#15984, answer score: 6

Revisions (0)

No revisions yet.