Strange Corrupt Pointer - Microsoft Bug??

J

James Niceguy

Hi,

I have written a simple program that does the following:

The main program will spown MAX_THREADS number of threads, each
of which will simply add to a global shared counter for MAX_COUNT
times and notify the main thread it has finished by clearing a
mutex before exiting. The main thread will simply check verify the
final result in the global shared counter, wait for each worker
thread has notify finishing, and exit.

The complete C program is at the end of this message. Anyway,
the problem is not in the logic of this program. It is really an
anomaly I encountered while testing it with different values of
MAX_THREADS.
I found that for some reason, if the MAX_THREADS value is 1 or 2 the
hRunMutex[0] will be corrupted during execution for no apparent
reason. The program will go into an infinite loop in CheckCounter()
function. I can detect this by checking if the return value of
WaitForSingleObject() function equals WAIT_FAILED, etc, but that's
another topic. So I was playing with the program and tried to
print out the value of hRunMutex[0] at various points and I found
that if I add on extra global variable definition, the whole problem
goes away! That is if I add "char func[10];".

For MAX_THREADS value 3 and above, the program works well with
or without that line. But for value 1 and 2, it has to have that line.
Otherwise it gets a currupt handle during execution and could not
finish.

I am really curious about the cause of this problem. I'd appreciate
if anyone can shed some light on it for me, because besides blaming
Microsoft, I am completely clueless. :)

And the reason I am blaming Microsoft is I am using Visual Studio
..NET to compile the program. Just create a project with Managed C++
Empty Project, and add this file to project to compile and run it.

Thanks!

Regards,
James

/* counters.c file.*/

/* This program will create MAX_THREADS number of threads. Each of
them
* will increment a shared counter for MAX_COUNT times, sleeping for a
* random number of milliseconds in between each increment. The main
* thread will wait until the shared counter reaches
MAX_THREADS*MAX_COUNT.
* It will then wait for enter key from input before exiting to allow
* examining the output.
*/

#include <windows.h>
#include <stdio.h>
#include <process.h>

#define MAX_THREADS 2
#define MAX_COUNT 3

/* getrandom returns a random number between min and max. */
#define getrandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) +
(min))

int main( void ); /* Thread 1: main */
void CountProc( int * MyID ); /* Threads 2 to MAX_THREADS:
Increment the shared counter */
void CheckCounter( void ); /* Function CheckCounter called
by main() */
void WriteMsg( int iThreadNum, int iMyCount, int iTotalCount ); /*
Display information */

HANDLE hRunMutex[MAX_THREADS]; /* Notification mutex */
int iThreadNum; /* Number of threads started */
HANDLE hCounterMutex; /* Shared counter mutex */
int iSharedCounter; /* Shared counter used by all threads
*/
int ThreadID[MAX_THREADS]; /* Thread ID for diaplay */
int done[MAX_THREADS] = {0}; /* Array for thread status */

char func[10]; // Necessary to make it work for MAX_THREADS = 1
and 2 cases. Microsoft bug?!

int main() /* Thread One */
{
/* Create the mutexes and reset thread count. */
int i;
iSharedCounter = 0;
for(i=0;i< MAX_THREADS;i++)
{
hRunMutex = CreateMutex( NULL, TRUE, NULL ); /* Set */
}
hCounterMutex = CreateMutex( NULL, FALSE, NULL ); /* Cleared */
iThreadNum = 0;

WriteMsg( 0, 0, iSharedCounter );

/* Create the counting threads. */
while( iThreadNum < MAX_THREADS )
{
iThreadNum++;
ThreadID[iThreadNum] = iThreadNum;
_beginthread( CountProc, 0, &ThreadID[iThreadNum] );
}

/* Wait until the shared counter reaches the limit. */
CheckCounter();
WriteMsg( 0, 0, iSharedCounter );

/* All threads done. Clean up handles. */
for(i=0;i<MAX_THREADS;i++)
{
/* if(done != 1) */
CloseHandle( hRunMutex );
}
CloseHandle( hCounterMutex);

/* Pause for 10 seconds before exiting */
printf("Press enter to exit...");
getchar();
}

void CheckCounter( void ) /* Check shared counter */
{
int i;

/* Check the share counter limit, sleep in between each check */
while ( iSharedCounter < MAX_COUNT * MAX_THREADS)
{
Sleep(getrandom(0,100));
}

/* Wait for the woker threads to exit first */
while ( iThreadNum > 0 )
{
for(i = 0;i<MAX_THREADS;i++)
{
if(done == 0 )
{
int ret = WaitForSingleObject( hRunMutex, 100 );
if(ret == WAIT_OBJECT_0 /*|| ret == WAIT_FAILED*/)
{
iThreadNum--;
done=ret+2;
}
}
}
Sleep(getrandom(0,100));
}
}

void CountProc( int *MyID )
{
int i=0;
do
{
/* Wait for counter to be available, then lock it. */
WaitForSingleObject( hCounterMutex, INFINITE );
iSharedCounter++;
WriteMsg(*MyID, i, iSharedCounter);
ReleaseMutex( hCounterMutex );

i++;
Sleep(getrandom(0, 5));
}
while(i < MAX_COUNT);

ReleaseMutex( hRunMutex[(*MyID)-1] );
}

void WriteMsg( int iThreadNum, int iMyCount, int iTotalCount )
{
printf("Thread ID: %d, Local Count: %d, Shared Count: %d \n",
iThreadNum, iMyCount, iTotalCount );
}
 
A

Andre Kostur

Hi,

I have written a simple program that does the following:

The main program will spown MAX_THREADS number of threads, each

Off-topic.... Standard C++ says nothing about Threads.
of which will simply add to a global shared counter for MAX_COUNT
times and notify the main thread it has finished by clearing a
mutex before exiting. The main thread will simply check verify the

Off-topic.... Standard C++ says nothing about Mutexes.
final result in the global shared counter, wait for each worker
thread has notify finishing, and exit.

The complete C program is at the end of this message. Anyway,
the problem is not in the logic of this program. It is really an
anomaly I encountered while testing it with different values of
MAX_THREADS.
I found that for some reason, if the MAX_THREADS value is 1 or 2 the
hRunMutex[0] will be corrupted during execution for no apparent
reason. The program will go into an infinite loop in CheckCounter()
function. I can detect this by checking if the return value of
WaitForSingleObject() function equals WAIT_FAILED, etc, but that's
another topic. So I was playing with the program and tried to
print out the value of hRunMutex[0] at various points and I found
that if I add on extra global variable definition, the whole problem
goes away! That is if I add "char func[10];".

For MAX_THREADS value 3 and above, the program works well with
or without that line. But for value 1 and 2, it has to have that line.
Otherwise it gets a currupt handle during execution and could not
finish.

I am really curious about the cause of this problem. I'd appreciate
if anyone can shed some light on it for me, because besides blaming
Microsoft, I am completely clueless. :)

And the reason I am blaming Microsoft is I am using Visual Studio
.NET to compile the program. Just create a project with Managed C++
Empty Project, and add this file to project to compile and run it.

Thanks!

Regards,
James

/* counters.c file.*/

/* This program will create MAX_THREADS number of threads. Each of
them
* will increment a shared counter for MAX_COUNT times, sleeping for a
* random number of milliseconds in between each increment. The main
* thread will wait until the shared counter reaches
MAX_THREADS*MAX_COUNT.
* It will then wait for enter key from input before exiting to allow
* examining the output.
*/

#include <windows.h>
#include <stdio.h>
#include <process.h>

#define MAX_THREADS 2
#define MAX_COUNT 3

/* getrandom returns a random number between min and max. */
#define getrandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) +
(min))

int main( void ); /* Thread 1: main */
void CountProc( int * MyID ); /* Threads 2 to MAX_THREADS:
Increment the shared counter */
void CheckCounter( void ); /* Function CheckCounter called
by main() */
void WriteMsg( int iThreadNum, int iMyCount, int iTotalCount );
/* Display information */

HANDLE hRunMutex[MAX_THREADS]; /* Notification mutex */
int iThreadNum; /* Number of threads started */
HANDLE hCounterMutex; /* Shared counter mutex */
int iSharedCounter; /* Shared counter
used by all threads */
int ThreadID[MAX_THREADS]; /* Thread ID for diaplay */
int done[MAX_THREADS] = {0}; /* Array for thread status */

char func[10]; // Necessary to make it work for MAX_THREADS = 1
and 2 cases. Microsoft bug?!

int main() /* Thread One */
{
/* Create the mutexes and reset thread count. */
int i;
iSharedCounter = 0;
for(i=0;i< MAX_THREADS;i++)
{
hRunMutex = CreateMutex( NULL, TRUE, NULL ); /* Set */
}
hCounterMutex = CreateMutex( NULL, FALSE, NULL ); /* Cleared */
iThreadNum = 0;

WriteMsg( 0, 0, iSharedCounter );

/* Create the counting threads. */
while( iThreadNum < MAX_THREADS )
{
iThreadNum++;
ThreadID[iThreadNum] = iThreadNum;


Undefined behaviour. The second time through this loop, you increment
iThreadNum (making it 2) and then attempted to write into an array beyond
its bounds (ThreadID, only has elements 0 and 1).
_beginthread( CountProc, 0, &ThreadID[iThreadNum] );
}

/* Wait until the shared counter reaches the limit. */
CheckCounter();
WriteMsg( 0, 0, iSharedCounter );

/* All threads done. Clean up handles. */
for(i=0;i<MAX_THREADS;i++)
{
/* if(done != 1) */
CloseHandle( hRunMutex );
}
CloseHandle( hCounterMutex);

/* Pause for 10 seconds before exiting */
printf("Press enter to exit...");
getchar();
}

void CheckCounter( void ) /* Check shared counter */
{
int i;

/* Check the share counter limit, sleep in between each check */
while ( iSharedCounter < MAX_COUNT * MAX_THREADS)
{
Sleep(getrandom(0,100));
}

/* Wait for the woker threads to exit first */
while ( iThreadNum > 0 )
{
for(i = 0;i<MAX_THREADS;i++)
{
if(done == 0 )
{
int ret = WaitForSingleObject( hRunMutex, 100 );
if(ret == WAIT_OBJECT_0 /*|| ret == WAIT_FAILED*/)
{
iThreadNum--;
done=ret+2;
}
}
}
Sleep(getrandom(0,100));
}
}

void CountProc( int *MyID )
{
int i=0;
do
{
/* Wait for counter to be available, then lock it. */
WaitForSingleObject( hCounterMutex, INFINITE );
iSharedCounter++;
WriteMsg(*MyID, i, iSharedCounter);
ReleaseMutex( hCounterMutex );

i++;
Sleep(getrandom(0, 5));
}
while(i < MAX_COUNT);

ReleaseMutex( hRunMutex[(*MyID)-1] );
}

void WriteMsg( int iThreadNum, int iMyCount, int iTotalCount )
{
printf("Thread ID: %d, Local Count: %d, Shared Count: %d \n",
iThreadNum, iMyCount, iTotalCount );
}
 
J

James Niceguy

Hi Andre,

Thank you for the answer! You are right on!! I changed the line to:

ThreadID[iThreadNum-1] = iThreadNum;

and the program works like a charm. Sorry if the policy is not to
discuss off-topic issues here. I will read the rules next time. Guess
I shouldn't be blaming MS so readily!

Regards,
James


Andre said:
Hi,

I have written a simple program that does the following:

The main program will spown MAX_THREADS number of threads, each

Off-topic.... Standard C++ says nothing about Threads.
of which will simply add to a global shared counter for MAX_COUNT
times and notify the main thread it has finished by clearing a
mutex before exiting. The main thread will simply check verify the

Off-topic.... Standard C++ says nothing about Mutexes.
final result in the global shared counter, wait for each worker
thread has notify finishing, and exit.

The complete C program is at the end of this message. Anyway,
the problem is not in the logic of this program. It is really an
anomaly I encountered while testing it with different values of
MAX_THREADS.
I found that for some reason, if the MAX_THREADS value is 1 or 2 the
hRunMutex[0] will be corrupted during execution for no apparent
reason. The program will go into an infinite loop in CheckCounter()
function. I can detect this by checking if the return value of
WaitForSingleObject() function equals WAIT_FAILED, etc, but that's
another topic. So I was playing with the program and tried to
print out the value of hRunMutex[0] at various points and I found
that if I add on extra global variable definition, the whole problem
goes away! That is if I add "char func[10];".

For MAX_THREADS value 3 and above, the program works well with
or without that line. But for value 1 and 2, it has to have that line.
Otherwise it gets a currupt handle during execution and could not
finish.

I am really curious about the cause of this problem. I'd appreciate
if anyone can shed some light on it for me, because besides blaming
Microsoft, I am completely clueless. :)

And the reason I am blaming Microsoft is I am using Visual Studio
.NET to compile the program. Just create a project with Managed C++
Empty Project, and add this file to project to compile and run it.

Thanks!

Regards,
James

/* counters.c file.*/

/* This program will create MAX_THREADS number of threads. Each of
them
* will increment a shared counter for MAX_COUNT times, sleeping for a
* random number of milliseconds in between each increment. The main
* thread will wait until the shared counter reaches
MAX_THREADS*MAX_COUNT.
* It will then wait for enter key from input before exiting to allow
* examining the output.
*/

#include <windows.h>
#include <stdio.h>
#include <process.h>

#define MAX_THREADS 2
#define MAX_COUNT 3

/* getrandom returns a random number between min and max. */
#define getrandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) +
(min))

int main( void ); /* Thread 1: main */
void CountProc( int * MyID ); /* Threads 2 to MAX_THREADS:
Increment the shared counter */
void CheckCounter( void ); /* Function CheckCounter called
by main() */
void WriteMsg( int iThreadNum, int iMyCount, int iTotalCount );
/* Display information */

HANDLE hRunMutex[MAX_THREADS]; /* Notification mutex */
int iThreadNum; /* Number of threads started */
HANDLE hCounterMutex; /* Shared counter mutex */
int iSharedCounter; /* Shared counter
used by all threads */
int ThreadID[MAX_THREADS]; /* Thread ID for diaplay */
int done[MAX_THREADS] = {0}; /* Array for thread status */

char func[10]; // Necessary to make it work for MAX_THREADS = 1
and 2 cases. Microsoft bug?!

int main() /* Thread One */
{
/* Create the mutexes and reset thread count. */
int i;
iSharedCounter = 0;
for(i=0;i< MAX_THREADS;i++)
{
hRunMutex = CreateMutex( NULL, TRUE, NULL ); /* Set */
}
hCounterMutex = CreateMutex( NULL, FALSE, NULL ); /* Cleared */
iThreadNum = 0;

WriteMsg( 0, 0, iSharedCounter );

/* Create the counting threads. */
while( iThreadNum < MAX_THREADS )
{
iThreadNum++;
ThreadID[iThreadNum] = iThreadNum;


Undefined behaviour. The second time through this loop, you increment
iThreadNum (making it 2) and then attempted to write into an array beyond
its bounds (ThreadID, only has elements 0 and 1).
_beginthread( CountProc, 0, &ThreadID[iThreadNum] );
}

/* Wait until the shared counter reaches the limit. */
CheckCounter();
WriteMsg( 0, 0, iSharedCounter );

/* All threads done. Clean up handles. */
for(i=0;i<MAX_THREADS;i++)
{
/* if(done != 1) */
CloseHandle( hRunMutex );
}
CloseHandle( hCounterMutex);

/* Pause for 10 seconds before exiting */
printf("Press enter to exit...");
getchar();
}

void CheckCounter( void ) /* Check shared counter */
{
int i;

/* Check the share counter limit, sleep in between each check */
while ( iSharedCounter < MAX_COUNT * MAX_THREADS)
{
Sleep(getrandom(0,100));
}

/* Wait for the woker threads to exit first */
while ( iThreadNum > 0 )
{
for(i = 0;i<MAX_THREADS;i++)
{
if(done == 0 )
{
int ret = WaitForSingleObject( hRunMutex, 100 );
if(ret == WAIT_OBJECT_0 /*|| ret == WAIT_FAILED*/)
{
iThreadNum--;
done=ret+2;
}
}
}
Sleep(getrandom(0,100));
}
}

void CountProc( int *MyID )
{
int i=0;
do
{
/* Wait for counter to be available, then lock it. */
WaitForSingleObject( hCounterMutex, INFINITE );
iSharedCounter++;
WriteMsg(*MyID, i, iSharedCounter);
ReleaseMutex( hCounterMutex );

i++;
Sleep(getrandom(0, 5));
}
while(i < MAX_COUNT);

ReleaseMutex( hRunMutex[(*MyID)-1] );
}

void WriteMsg( int iThreadNum, int iMyCount, int iTotalCount )
{
printf("Thread ID: %d, Local Count: %d, Shared Count: %d \n",
iThreadNum, iMyCount, iTotalCount );
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top