Today, let’s look at a trace log writer. It’s the kind of thing that you’d find in many applications; it simply does a printf and writes its output to a log file. In order to have maximum flexibility, the code re-opens the file every time the application writes to the filelog. But there’s still something wrong with this code.
This “what’s wrong with this code” is a little different. The code in question isn’t incorrect as far as I know, but it still has a problem. The challenge is to understand the circumstances in which it doesn’t work.
/*++ * LogMessage * Trace output messages to log file. * * Inputs: * FormatString - printf format string for logging. * * Returns: * Nothing * *--*/void LogMessage(LPCSTR FormatString, ...)#define LAST_NAMED_ARGUMENT FormatString{ CHAR outputBuffer[4096]; LPSTR outputString = outputBuffer; size_t bytesRemaining = sizeof(outputBuffer); ULONG bytesWritten; bool traceLockHeld = false; HANDLE traceLogHandle = NULL; va_list parmPtr; // Pointer to stack parms. EnterCriticalSection(&g_TraceLock); traceLockHeld = TRUE; // // Open the trace log file. // traceLogHandle = CreateFile(TRACELOG_FILE_NAME, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (traceLogHandle == INVALID_HANDLE_VALUE) { goto Exit; } // // printf the information requested by the caller onto the buffer // va_start(parmPtr, FormatString); StringCbVPrintfEx(outputString, bytesRemaining, &outputString, &bytesRemaining, 0, FormatString, parmPtr); va_end(parmPtr); // // Actually write the bytes. // DWORD lengthToWrite = static_cast<DWORD>(sizeof(outputBuffer) - bytesRemaining); if (!WriteFile(traceLogHandle, outputBuffer, lengthToWrite, &bytesWritten, NULL)) { goto Exit; } if (bytesWritten != lengthToWrite) { goto Exit; }Exit: if (traceLogHandle) { CloseHandle(traceLogHandle); } if (traceLockHeld) { LeaveCriticalSection(&g_TraceLock); traceLockHeld = FALSE; }}
/*++
* LogMessage
* Trace output messages to log file.
*
* Inputs:
* FormatString - printf format string for logging.
* Returns:
* Nothing
*--*/
void LogMessage(LPCSTR FormatString, ...)
#define LAST_NAMED_ARGUMENT FormatString
{
CHAR outputBuffer[4096];
LPSTR outputString = outputBuffer;
size_t bytesRemaining = sizeof(outputBuffer);
ULONG bytesWritten;
bool traceLockHeld = false;
HANDLE traceLogHandle = NULL;
va_list parmPtr; // Pointer to stack parms.
EnterCriticalSection(&g_TraceLock);
traceLockHeld = TRUE;
//
// Open the trace log file.
traceLogHandle = CreateFile(TRACELOG_FILE_NAME, FILE_APPEND_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (traceLogHandle == INVALID_HANDLE_VALUE)
{ goto Exit;
}
// printf the information requested by the caller onto the buffer
va_start(parmPtr, FormatString);
StringCbVPrintfEx(outputString, bytesRemaining, &outputString, &bytesRemaining, 0, FormatString, parmPtr);
va_end(parmPtr); //
// Actually write the bytes.
DWORD lengthToWrite = static_cast<DWORD>(sizeof(outputBuffer) - bytesRemaining);
if (!WriteFile(traceLogHandle, outputBuffer, lengthToWrite, &bytesWritten, NULL))
goto Exit;
if (bytesWritten != lengthToWrite)
Exit:
if (traceLogHandle)
CloseHandle(traceLogHandle);
if (traceLockHeld)
LeaveCriticalSection(&g_TraceLock);
traceLockHeld = FALSE;
One hint: The circumstance I’m thinking of has absolutely nothing to do with out of disk space issues.
As always, answers and kudos tomorrow.