今天嘗試着使用ucontext來實現一個輕量級的協程庫,結果運行測試程序時,發生了段錯誤
通過gdb調試發現錯誤是Cannot access memory at address,不過這個信息對我的幫助太小
然後我加入了一些調試用的輸出語句,就找到了真正的錯誤原因:我在創建一個協程時,需要傳入一個執行函數,我對此函數進行了封裝,作爲makecontext的函數入口,這個封裝函數會在原函數執行完畢後,做一些善後工作,譬如釋放協程結構體佔用的內存;可笑的是,我把協程使用的stack作爲成員放入了這個結構體,那麼當協程在運行時,這個stack指向的內存會受到保護,而我嘗試去free它,那麼就報了以上錯誤
struct Coroutine {
Scheduler *scher;
CoFunc func;
void *arg;
int state;
ucontext_t ctx;
char stack[DEFAULT_STACK_SZIE]; ----------------------> 協程運行使用的棧
};
// makecontext的函數入口
static void _coroutine_entry(uintptr_t *arg) {
Scheduler *s = (Scheduler *)arg;
assert(s != NULL);
int cid = s->running;
assert(cid >= 0 && cid < s->capacity);
Coroutine *co = s->cos[cid];
co->func(co->arg);
// coroutine done
free(co); ----------------------> 出錯原因
s->cos[cid] = NULL;
s->running = -1;
}