-4

I have been fighting with this for a loooong time. Looking around I don't seem to be able and find an answer. I simply create two detached threads and then use pthread_exit() on both of them but there are leaks every now and then.

And because I know people will ask me:

  1. Yes, I have read all the other questions and there is no real answer
  2. I mark the threads as detached
  3. I give enough time for the threads to initialize and die
  4. I have read the manual for pthread_exit and it is used correctly
  5. It compiles fine with -Wall

Code:

int threads_keepalive = 1;

void* thread_do(void *arg){
    while(threads_keepalive)
        sleep(1);
    pthread_exit(NULL);
}

int main(){

    /* Make threads */
    pthread_t* threads;
    threads = malloc(2 * sizeof(pthread_t));
    pthread_create(&threads[0], NULL, thread_do, NULL);
    pthread_create(&threads[1], NULL, thread_do, NULL);
    pthread_detach(threads[0]);
    pthread_detach(threads[1]);
    sleep(1); // MAKING SURE THREADS HAVE INITIALIZED

    /* Kill threads */
    threads_keepalive = 0;
    sleep(5); // MAKING SURE THREADS HAVE UNBLOCKED
    free(threads);

    return 0;
}

Running that code, although it is correct (at least in my eyes), I get memory leaks at random times. I run the same test multiple times with valgrind as below

> gcc test.c -pthread -o test && for i in {1..100}; do valgrind --leak-check=full --track-origins=yes ./test 2>&1 | grep frees; done
==4088==   total heap usage: 8 allocs, 4 frees, 2,230 bytes allocated
==4211==   total heap usage: 8 allocs, 4 frees, 2,230 bytes allocated
==4337==   total heap usage: 8 allocs, 4 frees, 2,230 bytes allocated
==4463==   total heap usage: 8 allocs, 4 frees, 2,230 bytes allocated
==4590==   total heap usage: 8 allocs, 8 frees, 2,230 bytes allocated
==4717==   total heap usage: 8 allocs, 8 frees, 2,230 bytes allocated
==4853==   total heap usage: 8 allocs, 4 frees, 2,230 bytes allocated
==4981==   total heap usage: 8 allocs, 8 frees, 2,230 bytes allocated
==5110==   total heap usage: 8 allocs, 8 frees, 2,230 bytes allocated
==5239==   total heap usage: 8 allocs, 8 frees, 2,230 bytes allocated
..

What is going on??

Update: Creating one thread instead of two, doesn't show memory leaks.

Pithikos
  • 18,827
  • 15
  • 113
  • 136
  • 2
    Well, to start with maybe you should have read the man for pthread_create(), specifically, the signature of thread_start(). – Martin James Jan 06 '15 at 17:31
  • There is no `thread_start()` function. WTF are you talking about? – Lee Daniel Crocker Jan 06 '15 at 17:41
  • 1
    It's on the man pages. In your code, 'thread_do()' should take a void* parameter. I'm not saying that this will definitely have any influence on your results, but you were so insistent that you had checked so much stuff.. – Martin James Jan 06 '15 at 17:46
  • Also, what @2501 says re. debugging this. – Martin James Jan 06 '15 at 17:48
  • @MartinJames I insisted that much because there are always people like you that instead of helping out, prefer to be anal and point to random things or close legitable questions which just gets frustrating when someone actually needs help. – Pithikos Jan 06 '15 at 17:49
  • @2501 Creating one thread (instead of two) gives no memory leaks.. – Pithikos Jan 06 '15 at 17:52
  • Err.. you got the signature wrong. The signature you used is wrong. You used the wrong signature. Is that sufficiently anal? – Martin James Jan 06 '15 at 17:52
  • @MartinJames yes, and annoying and not helpful at all. Using the correct signature doesn't alter the behaviour. – Pithikos Jan 06 '15 at 17:57
  • 2
    Look, put the void* in. It will take, like 5 seconds, and then one possible source of UB has been vanquished. – Martin James Jan 06 '15 at 17:57
  • @MartinJames you mean to cast to `(void*)thread_do`? – Pithikos Jan 06 '15 at 17:59
  • 1
    void* thread_do(void *param){... – Martin James Jan 06 '15 at 18:00
  • Right, at last. OK, you still have the problem, but you know one more thing that it is not. – Martin James Jan 06 '15 at 18:07
  • You're accessing `threads_keepalive` without synchronization which is also UB. In practice `sleep` probably provides the necessary compiler barrier and memory barrier to make this a non-issue, but it's still invalid multithreaded code. In the absence of join you should be using a proper synchronization primitive like semaphores or cond vars to wait for the threads to exit. – R.. GitHub STOP HELPING ICE Jan 06 '15 at 18:12
  • Use a volatile int for the keepalive. Use join() to ensure that the threads are, indeed terminated. – Martin James Jan 06 '15 at 18:12

1 Answers1

0

The title of your question is wrong -- you're not using threads correctly. But I don't think your memory leak is related to any of your instances of undefined behavior. It's just a spurious "leak" reported by valgrind due to (assuming you're using a Linux system with glibc) glibc internals. See these related questions:

Community
  • 1
  • 1
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711