user2847598
user2847598

Reputation: 1299

Do threads have different stacks and heaps?

Threads have their own stacks, but share the same heap [see: Do threads have a distinct heap?].

However, can someone explain the output of following program?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void f(void)
{
    char *pt = malloc(1024);
    printf("     f(). stack: %p, malloc: %p\n", &pt, pt);
}

void *thread_func(void *i)
{
    char *pt = malloc(1024);
    printf("thread(). stack: %p, malloc: %p\n", &pt, pt);
    return NULL;
}

int main(void)
{
    char *pt = malloc(1024);

    printf("  main(). stack: %p, malloc: %p\n", &pt, pt);
    f();
    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, thread_func, NULL);
    pthread_create(&thread2, NULL, thread_func, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    while(1);
    return 0;
}

[/tmp/t1]$ a.out
  main(). stack: 0x7fff9bedff88, malloc: 0x1527010      -> using same stack and heap with f()
     f(). stack: 0x7fff9bedff48, malloc: 0x1527420      -> using same stack and heap with main()
thread(). stack: 0x7f3c67378ea8, malloc: 0x7f3c580008c0 -> own stack and heap? (first thread)
thread(). stack: 0x7f3c67d79ea8, malloc: 0x7f3c600008c0 -> own stack and heap? (second thread)

$ pmap 106202
106202:   a.out
0000000000400000      4K r-x--  /tmp/t1/a.out
0000000000600000      4K rw---  /tmp/t1/a.out
0000000001527000    132K rw---    [ anon ]              -> heap for main() and f()
0000003c57200000    128K r-x--  /lib64/ld-2.12.so
0000003c5741f000      4K r----  /lib64/ld-2.12.so
0000003c57420000      4K rw---  /lib64/ld-2.12.so
0000003c57421000      4K rw---    [ anon ]
0000003c57600000   1576K r-x--  /lib64/libc-2.12.so
0000003c5778a000   2044K -----  /lib64/libc-2.12.so
0000003c57989000     16K r----  /lib64/libc-2.12.so
0000003c5798d000      4K rw---  /lib64/libc-2.12.so
0000003c5798e000     20K rw---    [ anon ]
0000003c57e00000     92K r-x--  /lib64/libpthread-2.12.so
0000003c57e17000   2048K -----  /lib64/libpthread-2.12.so
0000003c58017000      4K r----  /lib64/libpthread-2.12.so
0000003c58018000      4K rw---  /lib64/libpthread-2.12.so
0000003c58019000     16K rw---    [ anon ]
00007f3c58000000    132K rw---    [ anon ]               -> malloc (first thread)
00007f3c58021000  65404K -----    [ anon ]
00007f3c60000000    132K rw---    [ anon ]               -> malloc (second thread)
00007f3c60021000  65404K -----    [ anon ]
00007f3c66979000      4K -----    [ anon ]
00007f3c6697a000  10240K rw---    [ anon ]               -> stack (10240K) (first thread)
00007f3c6737a000      4K -----    [ anon ]
00007f3c6737b000  10252K rw---    [ anon ]               -> stack (10252K?) (second thread)
00007f3c67d88000      8K rw---    [ anon ]
00007fff9becc000     84K rw---    [ stack ]              -> stack for main() and f()
00007fff9bf42000      4K r-x--    [ anon ]
ffffffffff600000      4K r-x--    [ anon ]
 total           157776K

It seems two threads have different stacks and heaps.

Another question is ulimit -s shows 10240 but one thread's stack is 10240K, the other is 10252K.

The program runs on a 64-bit machine. OS: Red Hat Enterprise Linux Server release 6.4 (Santiago), kernel: 2.6.32, and gcc: 4.4.7.

Thanks.

---- updated:

Used a 32-bit OS (Ubuntu 12.04) and found that there is just one heap area for both threads. But still it is an area different from the heap of main() and f().

Can anyone try on their machine to verify?

In above link and other resources, people said there is one heap for all threads because threads have to share data. Can anyone give example how two threads share data via heap? If the 32-bit OS has one heap and threads can use to share, how about the distinct heaps in the original 64-bit OS example?

Thanks.

Upvotes: 1

Views: 393

Answers (1)

Voo
Voo

Reputation: 30216

The most important part: The heap is an implementation detail just as much as the stack is and there are dozens of different ways to implement it.

In reality, every serious implementation for a desktop or server environment will use some kind of thread-local storage though because you want to minimize synchronization overhead. For one well known example see tcmalloc. Consequently it'S not particularly surprising that allocations will end up in different parts of the address space (although that would happen relatively easily even with a simple malloc - a first fit with free list for example)

Upvotes: 2

Related Questions