Why does _stprintf_s overwrite other variables, but _stprintf is not?
I am using visual studio for a win32 programming class. I have a global array of string, declared as TCHAR **bufTh
, allocated in memory, like
bufTh = (TCHAR**)malloc(nOfTh*sizeof(TCHAR*));
for (i = 0; i < nOfTh; i++)
bufTh[i] = (TCHAR*)malloc(BUF_LEN*sizeof(TCHAR));
then I have some streams each writing to a different string in that array. I noticed that if I use _stprintf_s(bufTh[iTh], BUF_LEN, _T("%s\\"), findData.cFileName);
, after this operation, some other global variables (in my case semaphores) are overwritten, and if I use _stprintf
(without _s) everything will be fine.
Why? Where am I going wrong?
I also tried as an experiment to use a struct array containing a string, for example typedef struct{TCHAR buf[BUF_LEN];} mystr_t;
, and then allocated bufTh = (mystr_t*)malloc(nOfTh*sizeof(mystr_t));
. In this case, it _stprintf_s
works as expected, which does not cause problems.
EDIT: here is mcve
#define UNICODE
#define _UNICODE
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#define BUF_LEN _MAX_PATH+1
typedef struct{
DWORD iTh;
} tdata_t;
TCHAR **bufTh;
PHANDLE sem;
//DWORD WINAPI rThread(LPVOID pThParam);
int _tmain(int argc, LPTSTR argv[]){
DWORD i, nOfTh;
PHANDLE hthread;
tdata_t *tdata;
nOfTh = 1;
// global array of buffers, one for each reading thread
bufTh = (TCHAR**)malloc(nOfTh*sizeof(TCHAR*));
for (i = 0; i < nOfTh; i++)
bufTh[i] = (TCHAR*)malloc(BUF_LEN*sizeof(TCHAR));
// array of thread data, to pass to threads
tdata = (tdata_t*)malloc(nOfTh*sizeof(tdata_t));
for (i = 0; i < nOfTh; i++){
tdata[i].iTh = i;
}
// array of semaphores, one for each thread
sem = (PHANDLE)malloc((nOfTh)*sizeof(HANDLE));
for (i = 0; i < nOfTh; i++)
sem[i] = CreateSemaphore(NULL, 0, 1, NULL);
// array of threads
/*hthread = (PHANDLE)malloc(nOfTh*sizeof(HANDLE));
for (i = 0; i < nOfTh; i++)
hthread[i] = CreateThread(NULL, 0, &rThread, (LPVOID)&tdata[i], 0, NULL);*/
i = 0;
// BREAKPOINT HERE
_stprintf_s(bufTh[i], BUF_LEN, _T("%s\\"), _T("the string that I want to write there"));
// BREAKPOINT HERE
WaitForSingleObject(sem[i], INFINITE);
//WaitForMultipleObjects(nOfTh, hthread, TRUE, INFINITE);
system("pause");
return 0;
}
source to share
also in my entries semaphores are overwritten with value 0xfefefefe
This is a "magic value" written with safe CRT functions (eg _stprintf_s) to help you debug buffer length errors. The debug build of these functions fills the entire buffer using 0xfe as the padding value.
_stprintf_s(bufTh[i], BUF_LEN, ...));
So, you know that the size of the thBuf [0] buffer is not actually BUF_LEN. In other words, the call to malloc () is wrong.
#define BUF_LEN _MAX_PATH+1
This is an evil macro and is causing your problem. It expands to
bufTh[i] = (TCHAR*)malloc(_MAX_PATH + 1*sizeof(TCHAR));
Not what you meant, of course. Fix:
#define BUF_LEN (_MAX_PATH+1)
Additional parentheses are critical. Otherwise, this is a good reason to start using the keyword const
.
source to share