Last active
November 11, 2015 00:40
-
-
Save dnikku/a18d94ccdcd8434a5b87 to your computer and use it in GitHub Desktop.
_beginthreadex/CreateThread leaks when using CRT or not
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
/* | |
stdafx.f: | |
#include <time.h> | |
#include <stdio.h> | |
#include <tchar.h> | |
#include <Windows.h> | |
#include <process.h> | |
*/ | |
static LONG g_scheduledThreads = 0; // count nr of scheduled threads | |
static LONG g_executedThreads = 0; // count executed successfully | |
void printCounts(int step) { | |
printf(" step:%d, scheduled:%d, completed:%d\n", step, g_scheduledThreads, g_executedThreads); | |
} | |
/* | |
just paste the crt\src\time64.c, removing some comments ... | |
#define EPOCH_BIAS 116444736000000000i64 | |
typedef union { | |
unsigned __int64 ft_scalar; | |
FILETIME ft_struct; | |
} FT; | |
__time64_t __cdecl _time64( | |
__time64_t *timeptr | |
) | |
{ | |
__time64_t tim; | |
FT nt_time; | |
GetSystemTimeAsFileTime(&(nt_time.ft_struct)); | |
tim = (__time64_t)((nt_time.ft_scalar - EPOCH_BIAS) / 10000000i64); | |
if (tim > _MAX__TIME64_T) | |
tim = (__time64_t)(-1); | |
if (timeptr) | |
*timeptr = tim; | |
return tim; | |
} | |
*/ | |
void executeThread(int v){ | |
//1. leaks: | |
time_t tt = _time64(NULL); | |
//2. leaks: FILETIME ft; GetSystemTimeAsFileTime(&ft); | |
//3. no leaks: SYSTEMTIME stm; GetSystemTime(&stm); | |
//4. no leaks: char sz[524 * 1024]; sprintf(sz, "Salutare de la mare"); | |
InterlockedAdd(&g_executedThreads, v); | |
} | |
static DWORD WINAPI createthread_wrapper(void *arg) { | |
executeThread(1); | |
return 0; | |
} | |
bool createthread_factory() { | |
InterlockedAdd(&g_scheduledThreads, 1); | |
DWORD id; | |
HANDLE hThread = CreateThread(NULL, 640 * 1024, createthread_wrapper, NULL, 0x00010000, &id); | |
if (hThread == NULL) { | |
DWORD lastError = GetLastError(); | |
printf("CreateThread failed. err(%d). exiting ...\n", lastError); | |
return false; | |
} | |
else { | |
CloseHandle(hThread); | |
return true; | |
} | |
} | |
static unsigned int __stdcall _beginthreadex_wrapper(void *arg) { | |
executeThread(1); | |
return 0; | |
} | |
bool _beginthreadex_factory() { | |
InterlockedAdd(&g_scheduledThreads, 1); | |
unsigned int id; | |
HANDLE handle = (HANDLE)_beginthreadex(NULL, | |
6400 * 1024, _beginthreadex_wrapper, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, &id); | |
if (handle == 0) { | |
DWORD lastError = GetLastError(); | |
printf("_beginthreadex failed. err(%d); errno(%d). exiting ...\n", lastError, errno); | |
return false; | |
} | |
else { | |
CloseHandle(handle); | |
return true; | |
} | |
} | |
int _tmain(int argc, _TCHAR* argv[]) { | |
printf("starting ...\n"); | |
bool(*f_wrapper) () = 1 ? _beginthreadex_factory : createthread_factory; | |
while (true) { | |
int i; | |
for (i = 0; i < 1000000; i++) { | |
if (!f_wrapper()){ | |
Sleep(5 * 1000); // wait some time ... | |
printCounts(i); | |
// try to create 10 more threads | |
for (int j = 0; j < 10; j++) f_wrapper(); | |
break; // exit from for ... | |
} | |
if (i % 10000 == 0) printCounts(i); // print progress | |
} | |
Sleep(4 * 1000); // wait to stop all threads | |
printCounts(i); | |
printf("read char:"); | |
getchar(); // press enter to rerun | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment