0

Just a small program to test multi-threading. It supposed to print out a 'Hello' message with the index of the thread and the thread location.

I read why pthread cause memory leak and tried to use pthread_join. It seems that the memory leak still remains

Following is my code:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>

void runMe(int *arg) {
    printf("Hello %d from %x\n", *arg, (unsigned int)pthread_self());
    int *ret = (int*)malloc(sizeof(int));
    *ret = *arg + 4; // note this value '4' will be different in the quiz!

    pthread_exit((void*)ret);
}

int run_threads(int n) {
    pthread_t thr[n];
    int thr_args[n];
    int *ptr = 0;
    int total = 0;

    for (int i=0; i<n; i++) {
        thr_args[i] = i;
        pthread_create(&thr[i], NULL, (void*)runMe, &thr_args[i]);

    }
    for (int j=0; j<n; j++) {
        pthread_join(thr[j], (void*)ptr++);
        total += thr_args[j];
    }
    return total;
}

int main() {

    run_threads(10);

}

Following is the result of running valgrind:

==10292== 
==10292== HEAP SUMMARY:
==10292==     in use at exit: 1,654 bytes in 14 blocks
==10292==   total heap usage: 26 allocs, 12 frees, 5,454 bytes allocated
==10292== 
==10292== LEAK SUMMARY:
==10292==    definitely lost: 40 bytes in 10 blocks
==10292==    indirectly lost: 0 bytes in 0 blocks
==10292==      possibly lost: 0 bytes in 0 blocks
==10292==    still reachable: 1,614 bytes in 4 blocks
==10292==         suppressed: 0 bytes in 0 blocks
==10292== Rerun with --leak-check=full to see details of leaked memory
==10292== 
==10292== For counts of detected and suppressed errors, rerun with: -v
==10292== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
gjjhhh_
  • 169
  • 3
  • 21
  • 1
    I think you need to read more about [the `pthread_join` function](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html), especially what the second argument is used for. – Some programmer dude Aug 05 '17 at 06:31
  • Thanks for replying!! So I initialized a pointer pointing to my thread and used `pthread_join(*thr, (void*)ptr)`. It worked but there were still 4 bytes of memory leaks. I tried to use `free(ret)` in `runMe` it is not helping. – gjjhhh_ Aug 05 '17 at 06:41
  • Where do you declare the ptr in `(void*)ptr`? Can you update that in your code? – fileyfood500 Aug 05 '17 at 06:51
  • I have updated. – gjjhhh_ Aug 05 '17 at 06:56

2 Answers2

4

Your leak is because the memory you allocate has no corresponding free action.

The code you're using appears to be trying to convey a dynamic allocation back to the caller. Proper use of pthread_join and its second parameter can recoup that memory pointer, which can then be properly freed.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>

void* runMe(void *pv)
{
    int *arg = pv;
    printf("Hello %d from %x\n", *arg, (unsigned int)pthread_self());
    int *ret = malloc( sizeof *ret );
    *ret = *arg + 4; // note this value '4' will be different in the quiz!
    return ret;
}

int run_threads(int n) {
    pthread_t thr[n];
    int thr_args[n];
    int total = 0;

    for (int i=0; i<n; i++) {
        thr_args[i] = i;
        pthread_create(thr+i, NULL, runMe, thr_args+i);

    }
    for (int j=0; j<n; j++)
    {
        // reap pointer from resulting thread.
        void *res = NULL;
        pthread_join(thr[j], &res);

        int *ires = res;
        printf("ires = %p; *ires = %d\n", ires, *ires);
        free(ires);

        total += thr_args[j];
    }
    return total;
}

int main()
{
    run_threads(10);
}

Output (varies)

Hello 9 from b0a71000
Hello 0 from b05df000
Hello 7 from b096d000
Hello 2 from b06e3000
Hello 1 from b0661000
Hello 4 from b07e7000
Hello 3 from b0765000
Hello 5 from b0869000
Hello 6 from b08eb000
Hello 8 from b09ef000
ires = 0x600000; *ires = 4
ires = 0x2009e0; *ires = 5
ires = 0x600010; *ires = 6
ires = 0x500010; *ires = 7
ires = 0x2009f0; *ires = 8
ires = 0x2012c0; *ires = 9
ires = 0x600020; *ires = 10
ires = 0x400040; *ires = 11
ires = 0x400050; *ires = 12
ires = 0x500000; *ires = 13

I also took liberty to fix your incorrect, non-compliant function signature you were using. pthread_create requires the form:

void *proc(void *)

for the thread procedure. Anything not of that form isn't compliant, and should be avoided.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
0

Notice that you are calling malloc in the runMe function. Each call to malloc : malloc(sizeof(int)) allocates 4 bytes of memory. You make 10 threads, so 40 bytes are allocated. But you never free this memory. In order to free the memory, you must call free on the memory address:

int *ret = (int*)malloc(sizeof(int));
// code using ret
free(ret);

If you free the addresses after using them, you will have no memory leaks.

fileyfood500
  • 1,199
  • 1
  • 13
  • 29
  • Thanks for your answer. Unfortunately, It does not help with my problem – gjjhhh_ Aug 05 '17 at 06:46
  • No worries, you would need to free the pointer where you last use it, and since you are returning the ret ptr, it wouldn't make sense to free it before then. – fileyfood500 Aug 05 '17 at 06:53