I am writing a function which prints a formatted string in a Windows console. It takes a simple C string which is a single byte string, converts it into a wide string for the Windows O.S., sends it to the console and frees both buffers. The buffer of a single-byte string is freed normally, but when I free the wide string, the program crashes.
When I free the allocated memory right after the call to WriteConsoleW
, the application crashes.
Why does it crash ?
Do I need to free that ws
buffer, supplied to the WriteConsoleW
function, or does it free it internally and automagically ?
Here is my function:
void console_print(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char *buf = smprintf(fmt, args);
va_end(args);
if (buf == NULL) {
return;
}
PDWORD cChars = NULL;
HANDLE std_out = GetStdHandle(STD_OUTPUT_HANDLE);
LPWSTR ws = CHARtoWCHAR(buf, CP_ACP);
WriteConsoleW(std_out, ws, wcslen(ws), cChars, NULL);
free(ws); // This line crashes the program.
free(buf);
}
The second buffer for a wide string, the ws
, is allocated inside the CHARtoWCHAR
function:
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) {
size_t len = strlen(str) + 1;
int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0);
LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed);
MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed);
return wstr;
}
The smprintf
function creates a C formatted string.
// Creates a buffer and fills it with a string formatted with the specified
// format and arguments. Caller must free the buffer after usage.
char *smprintf(const char *fmt, ...) {
va_list args;
// 1. Measure the required size of buffer.
va_start(args, fmt);
int len = vsnprintf(NULL, 0, fmt, args);
va_end(args);
// 2. Create the buffer.
char *buf = malloc(++len);
if (buf == NULL) {
return NULL;
}
// 3. Fill the buffer.
va_start(args, fmt);
vsnprintf(buf, len, fmt, args);
va_end(args);
return buf; // Do not forget to use: free(x).
}
Thank you.
Thanks to Jabberwocky.
I forgot to use the LocalFree
.
LocalFree(ws);
free(buf);