[Gc] random problem in simple c++ program

Achilleas Margaritis axilmar at otenet.gr
Wed Dec 12 10:17:01 PST 2007


Hi,

I've got a big problem: the GC randomly crashes in a very simple C++ 
program that does the following:

1) the main thread creates a thread which spawns 10 allocation threads.
2) each allocation thread allocates a certain number of GC'd blocks.
3) the cleanup routine waits for threads to terminate.

I am using pthreads-win32 with the GC, registering threads on my own, 
using GC_register_my_thread.

I've got a different (seemingly random) problem each time I run the program:

1) stack pointer out of range: "GC Warning: Thread stack pointer 
0xa6f784 out of range, pushing everything" appears on the IDE output window.

2) random access violations like "First-chance exception at 0x0041f919 
in test_gc.exe: 0xC0000005: Access violation reading location 0x00a70000"

3) a random access violation which crashes the C runtime system with a 
message. See image at 
http://img141.imageshack.us/img141/232/gcproblem1av6.jpg.

4) sometimes nothing happens: the program gets stuck in the collector 
loop, without any action.

5) a message saying 'dirty bit is not setup'. Please see image at 
http://img167.imageshack.us/img167/9956/gcproblem2jz1.jpg.

6) sometimes I get multiple message boxes from the crt runtime 
terminating in an unusual way: 
http://img254.imageshack.us/img254/7447/gcproblem3fs2.jpg.

7) Once I got the message 'duplicate large block deallocation'.

Is it something I am doing wrong?

Here is the program's code:

#include <gc.h>
#include <pthread.h>
#include <semaphore.h>
#include <list>
using namespace std;

//number of allocations per thread
const int MAX_ALLOC = 100;

//global mutex
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

//list of threads
list<pthread_t> threads;

//required for list of threads
bool operator == (pthread_t a, pthread_t b) {
     return pthread_equal(a, b) != 0;
}

//synchronized add thread
void add_thread(pthread_t handle) {
     pthread_mutex_lock(&mutex);
     threads.push_back(handle);
     pthread_mutex_unlock(&mutex);
}

//synchronized remove thread
void remove_thread(pthread_t handle) {
     pthread_mutex_lock(&mutex);
     threads.remove(handle);
     pthread_mutex_unlock(&mutex);
}

//synchronized threads empty
bool threads_empty() {
     pthread_mutex_lock(&mutex);
     bool result = threads.empty();
     pthread_mutex_unlock(&mutex);
     return result;
}

//used for allocating random sizes
int rnd(int i) {
     return rand() % i;
}

//allocates memory
void *allocatorThread(void *p) {
     //register thread
     GC_stack_base sb;
     GC_get_stack_base(&sb);
     GC_register_my_thread(&sb);

     printf("beginning allocator thread\n");

     //allocate memory
     for(int i = 0; i < MAX_ALLOC; ++i) {
         void *p = GC_MALLOC(10 + rnd(1000));
     }

     printf("ending allocator thread\n");

     //remove thread from list
     remove_thread(pthread_self());

     //unregister thread
     GC_unregister_my_thread();
     return 0;
}

//the thread that spawns the allocator threads
void *spawnerThread(void *p) {
     //register the thread
     GC_stack_base sb;
     GC_get_stack_base(&sb);
     GC_register_my_thread(&sb);

     printf("beginning spawner thread\n");

     //create other threads
     for(int i = 0; i < 10; ++i) {
         pthread_t handle;
         pthread_create(&handle, 0, allocatorThread, 0);
         add_thread(handle);
     }

     printf("ending spawner thread\n");

     //remove the thread
     remove_thread(pthread_self());

     //unregister the thread
     GC_unregister_my_thread();
     return 0;
}

//cleanup; called at exit
void cleanup() {
     sem_t sem;
     sem_init(&sem, 0, 0);

     //periodically check if all threads have terminated
     while (!threads_empty()) {
         timespec time = {1, 0};
         sem_timedwait(&sem, &time);
     }
     sem_destroy(&sem);

     pthread_mutex_destroy(&mutex);
}

//main
int main() {
     //init the gc
     GC_INIT();

     //install an exit handler
     atexit(cleanup);

     //create and register the main thread
     pthread_t handle;
     pthread_create(&handle, 0, spawnerThread, 0);
     add_thread(handle);

     getchar();
     return 0;
}



More information about the Gc mailing list