Reputation: 1299
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
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