Q: Segmentation when using malloc to allocate stack for context, but not when using local array I am trying to make a user level thread library, but when I tried to set the context of one of those threads, I received a segmentation fault error. I made a stripped version of all my code and narrowed it down (I think) to one weird thing. If I use malloc() to provide a stack for the thread context, it doesn't work. Weirdly though, if I declare an array of same size on the current function's stack, it works as expected. I thought that, apart for the different areas in memory, both approaches would be completely equivalent. After all, they are both pointers to some area of memory that's free to use.
The important lines are:


*

*char cstack[1024];, and

*char *cstack = (char *)malloc(1024);
Both in thread.c, shown below. If I comment the first one and not the second, segmentation fault ensues. If I do the opposite, all is (seems?) fine.
This is the program I used to test it, test.c:
#include <stdlib.h>
#include "thread.h"

int main(int argc, char** argv) {
    ccreate(NULL, NULL);
    return 0;
}

Here is thread.h:
#ifndef __cthread__
#define __cthread__

int ccreate (void* (*start)(void*), void *arg);

#endif

Here is (most importantly) thread.c:
#include <stdlib.h>
#include <stdio.h>
#include <ucontext.h>
#include "logging.c"
#include "cdata.h"
#include "thread.h"

#undef LOGLEVEL
#define LOGLEVEL 5

ucontext_t m;
int been_here;

static TCB_t *TCB_init(int tid) {
    floginfo("initializing TCB %d", tid);
    TCB_t *thr = (TCB_t *)malloc(sizeof(TCB_t));

    thr->tid = tid;
    thr->state = PROCST_APT;

    flogdebug("initializing context at address %p", &(thr->context));
    if (getcontext(&(thr->context)) == -1) logerror("error initializing context");
    thr->context.uc_link = &m;

    return thr;
}

static void say_hey(void) {
    been_here = 1;
    loginfo("hey");
}

int ccreate (void* (*start)(void*), void *arg) {
    static int last_tid = -1;

    //char cstack[1024]; /* doesn't segfault */
    char *cstack = (char *)malloc(1024); /* segfaults */

    floginfo("creating thread %d.", last_tid + 1);
    TCB_t *thr;
    thr = TCB_init(++last_tid);
    thr->context.uc_stack.ss_sp = cstack;
    thr->context.uc_stack.ss_size = 1024;

    been_here = 0;
    getcontext(&m);

    if (!been_here) {

        flogdebug("making context at address %p", &(thr->context));
        logdebug("calling: makecontext(&(thr->context), say_hey, 0);");
        makecontext(&(thr->context), say_hey, 0);

        flogdebug("setting context at address %p", &(thr->context));
        logdebug("calling: setcontext(&(thr->context))");
        setcontext(&(thr->context));
    }
    logdebug("came back from setcontext");

    logdebug("exiting");

    return 0;
}

This is where the TCB_t (thread control block) type is defined, cdata.h:
#ifndef __cdata__
#define __cdata__

#define PROCST_CRE  0
#define PROCST_APT  1
#define PROCST_EXEC 2
#define PROCST_BLOC 3
#define PROCST_TERM 4

typedef struct s_TCB {
    int     tid;
    int     state;
    ucontext_t  context;
} TCB_t;

#endif

And here is (very unimportant, I think) logging.c:
#include <stdio.h>
#include <stdarg.h>

#define LOGLEVEL 6
#define LVL_DEBUG 5
#define LVL_INFO 4
#define LVL_WARNING 3
#define LVL_ERROR 2
#define LVL_CRITICAL 1

void logdebug(const char *msg) {
    if (LOGLEVEL >= LVL_DEBUG) {
        fprintf(stderr, "DEBUG:    %s\n", msg);
    }
}

void loginfo(const char *msg) {
    if (LOGLEVEL >= LVL_INFO) {
        fprintf(stderr, "INFO:     %s\n", msg);
    }
}

void logwarning(const char *msg) {
    if (LOGLEVEL >= LVL_WARNING) {
        fprintf(stderr, "WARNING:  %s\n", msg);
    }
}

void logerror(const char *msg) {
    if (LOGLEVEL >= LVL_ERROR) {
        fprintf(stderr, "ERROR:    %s\n", msg);
    }
}

void logcritical(const char *msg) {
    if (LOGLEVEL >= LVL_CRITICAL) {
        fprintf(stderr, "CRITICAL: %s\n", msg);
    }
}

void flogdebug(const char *fmt, ...) {
    char buff[1024];
    va_list args;
    va_start(args, fmt);
    vsprintf(buff, fmt, args);
    va_end(args);
    logdebug((const char *)buff);
}

void floginfo(const char *fmt, ...) {
    char buff[1024];
    va_list args;
    va_start(args, fmt);
    vsprintf(buff, fmt, args);
    va_end(args);
    loginfo((const char *)buff);
}

void flogwarning(const char *fmt, ...) {
    char buff[1024];
    va_list args;
    va_start(args, fmt);
    vsprintf(buff, fmt, args);
    va_end(args);
    logwarning((const char *)buff);
}

void flogerror(const char *fmt, ...) {
    char buff[1024];
    va_list args;
    va_start(args, fmt);
    vsprintf(buff, fmt, args);
    va_end(args);
    logerror((const char *)buff);
}
void flogcritical(const char *fmt, ...) {
    char buff[1024];
    va_list args;
    va_start(args, fmt);
    vsprintf(buff, fmt, args);
    va_end(args);
    logcritical((const char *)buff);
}

Finally, compiling all with gcc -Wall thread.c test.c gives no warning. If char cstack[1024]; is uncommented, I get this:
INFO:     creating thread 0.
INFO:     initializing TCB 0
DEBUG:    initializing context at address 0x16d5018
DEBUG:    making context at address 0x16d5018
DEBUG:    calling: makecontext(&(thr->context), say_hey, 0);
DEBUG:    setting context at address 0x16d5018
DEBUG:    calling: setcontext(&(thr->context))
INFO:     hey
DEBUG:    came back from setcontext
DEBUG:    exiting

If char *cstack = (char *)malloc(1024); is uncommented, I get this:
INFO:     creating thread 0.
INFO:     initializing TCB 0
DEBUG:    initializing context at address 0x12f8428
DEBUG:    making context at address 0x12f8428
DEBUG:    calling: makecontext(&(thr->context), say_hey, 0);
DEBUG:    setting context at address 0x12f8428
DEBUG:    calling: setcontext(&(thr->context))
Segmentation fault (core dumped)

Any ideas at all are appreciated. I am mostly confused and pondering all I thought I knew.

A: According to this

stack_t uc_stack Stack used for this context. The value need not be
  (and normally is not) the stack pointer. See section 24.9 Using a
  Separate Signal Stack.

and this

size_t ss_size 
This is the size (in bytes) of the signal stack which
  'ss_sp' points to. You should set this to however much space you
  allocated for the stack. There are two macros defined in 'signal.h'
  that you should use in calculating this size:
SIGSTKSZ 
This is the canonical size for a signal stack. It is judged
  to be sufficient for normal uses.
MINSIGSTKSZ
This is the amount of signal stack space the operating
  system needs just to implement signal delivery. The size of a signal
  stack must be greater than this. For most cases, just using 

the minimum required size of stack is governed by MINSIGSTKSZ macro.

A: It happens to work if cstack is on your normal stack because you set up the stack pointer incorrectly and you're getting away with overwriting memory on the real stack rather than overwriting memory you got from malloc.
In which direction does the stack grow on your machine? If it grow like on a normal CPU (pretty much anything other than PA-RISC), where in your memory block should the initial stack pointer point? If you can't answer those two questions with "oh, of course, that's a silly mistake" you should reconsider this project, it only gets harder after here.

A: According to the man page, you should allocate at leat SIGSTKSZ for the stack size.
On my pc, this constant is equal to 8192. On your computer this constant may be greater than 1024.
