Search code examples
c++macrosnullptr

NULL_CLASS_PTR_DEREFERENCE when using __FILE__, __LINE__ and __FUNCTION__ in log macro


I have a strange behaviour in one of my programs. I have defined a macro LOG_FUNCTION that expands to

#define LOG_FUNCTION \
    { \
        std::string strFile = __FILE__; \
        std::string strLine = std::to_string(__LINE__); \
        std::string strFunction = __FUNCTION__; \
        logger.log(strFile + ", line " + strLine + ", " + strFunction + "()"); \
    } \
    CIndentor _indentor_(&logger);

declared in Logger.h. The logger is also declared in Logger.h:

// Declare the one and only logger object (which is defined in Logger.cpp):
extern CLogger logger;

The log-Function looks like this:

void CLogger::log(const string &strText)
{
    lock_guard<mutex> lockGuard(_mutex);

    m_count++;

    string strIndentation(m_indentation, ' ');

    string strTime = getCurrentDateTime();

    FILE* pFileStream = nullptr;
    errno_t err = fopen_s(&pFileStream, m_strLogFilePath.c_str(), "a+");
    if (err == 0)
    {
        fprintf(pFileStream, "[#%05d] [%s] %s%s\n", m_count, strTime.c_str(), strIndentation.c_str(), strText.c_str());  
        fclose(pFileStream); 
    }
}

Now sometimes my program crashes. Examining the heapdump with windbg this happens exactly at the line in the code where I call the LOG_FUNCTION-macro in one of my functions. This does not happen always and of course I use the macro in other places as well where no such crash happens. Only in a single function (where it is the first line):

void MyClass::SetInfoText(wstring& text)
{
    LOG_FUNCTION;  // <= this is the place where windbg says it crashes
    ...
}

Can anybody shed some light on this?

EDIT

added some code above to show where logger is declared


Solution

  • NULL_CLASS_PTR_DEREFERENCE means that something with this pointer is wrong - this is NULL.

    This could happen if a non-virtual member function is called on a null pointer at the first member accessed through this nullptr this.

    You need to look one step back on the stack and make sure this does not happen at the caller site.