1

Here is an example of a thread.


void* thrfun(void* arg)
{
    int var;
    var = 7;
    
    
    pthread_exit(NULL);
}

What happens to var when it exits. Is var de allocated, or is var still sitting in memory as a leak?

Is a thread function simply still a function, and all variables inside are local, meaning they get de allocated upon exit?

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • 1
    It's a thread function. Key word there is *function*. The same thing happens to *automatic* variables there that happens to *any* function. Once the scope is left, the automatic variables are destroyed. Is your question more about the differences in behavior of `return` vs. `pthread_exit` ? – WhozCraig Jun 17 '22 at 19:01
  • If you're concerned about `return (void *) x;` vs `pthread_exit((void *) x);`, see my recent answer: [c pthread still reachables](https://stackoverflow.com/a/72610521) The TL;DR `pthread_exit` will not do as thorough a cleanup as the `return` – Craig Estey Jun 17 '22 at 20:20
  • @CraigEstey Sounds like a good reason to use the standardized thread API instead. With `thrd_create`/[`thrd_exit`](https://en.cppreference.com/w/c/thread/thrd_exit) I assume no such surprises would occur? – Ted Lyngmo Jun 17 '22 at 21:07
  • @TedLyngmo Glad you saw this comment (I was considering one under your answer). No, `thrd_exit` is a wrapper around `pthread_exit`. And, if you look at the source code for `pthread_exit`, it calls `__do_cancel` so `thrd_exit/pthread_exit` is like doing `pthread_cancel(pthread_self());` – Craig Estey Jun 17 '22 at 21:14
  • @CraigEstey Cheers! :-) Is it so that the guarantees mentioned in the standard are a bit relaxed or is it just an implementation blunder in Posix-based implementations? The way I read it makes me think I should be able to trust `thrd_exit`. – Ted Lyngmo Jun 17 '22 at 21:18
  • @TedLyngmo It might be a `glibc` impl thing. But, I just looked at `freebsd` library source. There, `pthread_exit` does an [internal] "unwind". `glibc` calls `__pthread_unwind`. So, they both try to do the same thing. But, this "unwind" seems to be imperfect. It can't get to all the things that the launch helper function has access to (glibc). – Craig Estey Jun 17 '22 at 21:32
  • @TedLyngmo The reason I do clean unwind myself is that I have my own wrappers for this [bad pseudocode]: `craig_pcreate(thr,at,fptr,vp) { struct craig_task_block tsk; tsk.arg = vp; tsk.fnc = fnc; pthread_create(thr,at,craig_launch,tsk) } void *craig_launch(struct craig_task_block *tsk) { tskcur = tsk; do_stuff(); void *ret = tsk->fnc(tsk->arg); do_stuff2(); return ret; }` – Craig Estey Jun 17 '22 at 21:39
  • Cudos for digging into the different implementation details! I've tried to take a step away from platform and implementation details and try to use as much standard features as possible nowadays. If the standard has certain requirements on implementations claiming to be conforming, I expect those implementations to work on "getting there". I know it's a bit naive, but ... :-) – Ted Lyngmo Jun 17 '22 at 21:42
  • @TedLyngmo In the other question, the "leak" is probably harmless [otherwise, we'd have massive breakage on many apps] so okay for `pthread_exit`--it took `valgrind` to find it and its classification wasn't a "leak" in the regular sense. – Craig Estey Jun 17 '22 at 21:44
  • I've used `valgrind` and `-fsanitize=thread` (and `-fsanitize=address,undefined` separately) on all my `pthread` based programs and have never found `valgrind` to complain (other than "when it should"). Perhaps a built-in knowledge in `valgrind`? – Ted Lyngmo Jun 17 '22 at 21:50

1 Answers1

4

The local variables declared in thrfun(void* arg) are placed on the thread's stack (if the system has a stack) and will be released as soon as the function returns, just like with any other function.

Is var de allocated, or is var still sitting in memory as a leak?

The memory claimed by var will be released.

If you instead do manual memory allocation, with malloc for example, that memory remains allocated (on the heap, if the system has a heap) until you free it, also just like with any other function.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • I updated the return value from 'R' to NULL. On a side note, do I need to include pthread_exit, or can I simply leave that out and the function will deallocate the locals like normal? – user19260951 Jun 17 '22 at 19:54
  • @user19260951 I updated my answer seconds after you changed `'R'` to `NULL` :-) You can simply leave the function with a `return NULL;`. That'll result in an implicit `pthread_exit(NULL);` – Ted Lyngmo Jun 17 '22 at 19:56
  • @user19260951 If the answer answered your question you may want to read this: [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers) – Ted Lyngmo Jul 03 '22 at 17:03