[cs631apue] thread stacks

Jan Schaumann jschauma at stevens.edu
Tue Oct 21 14:24:13 EDT 2025


Hello,

Yesterday, Tristan had asked about the arrangement of
thread stacks in virtual memory.  (Every thread gets
its own stack separate from each other and separate
from the main program's stack, although the threads
share the heap etc.) I had made the claim that with
ASLR, those stacks are equally as unpredictable as the
program's stack itself.

But since I don't do a lot with threads (see
https://shouldiusethreads.com/), I figured I better
verify this.  And lo and behold, I was wrong. :-)

Using the program below, we can see that while the
first thread's stack is at an unpredictable location,
each subsequent thread's stack is at a fixed offset
off the first thread's stack.

(You can determine what this offset is by adding the
stack size and the size of the guard page.)

Use this as confirmation that it's always best to
verify your understanding and not blindly listen to
your instructor. :-)

I think different OS may handle this differently,
however, and it may be useful to check if the same
predictable offset is used by e.g., OpenBSD, which I
think may have stronger protections (but I don't have
an OpenBSD system set up right now).

-Jan

----

#include <sys/resource.h>

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

#define NUM 4

void *
func(void *arg) {
	void *var;
	void *addr = &var;

	(void)printf("Thread %ld is at %p.\n", (long)arg, addr);
	return addr;
}

int
main() {
	long i;
	pthread_t threads[NUM];
	void *taddrs[NUM];

	(void)printf("Main at %p.\n", &i);

	for (i = 0; i < NUM; i++) {
		if (pthread_create(&threads[i], NULL, func, (void*)i) != 0) {
			perror("pthread_create");
			exit(EXIT_FAILURE);
		}
	}

	for (i = 0; i < NUM; i++) {
		if (pthread_join(threads[i], &taddrs[i]) != 0) {
			perror("pthread_join");
			exit(EXIT_FAILURE);
		}
	}

	(void)printf("\nStack address differences between threads:\n");
	for (i = 1; i < NUM; i++) {
		long diff = taddrs[i - 1] - taddrs[i];
		(void)printf("Thread %ld - Thread %ld: %ld bytes\n", i - 1, i, diff);
	}

	return EXIT_SUCCESS;
}



More information about the cs631apue mailing list