.? на указателе из C - это утверждение, а не проверка. Оно говорит, что null здесь невозможен. В сборке с проверками безопасности null вызывает панику, а в ReleaseFast или ReleaseSmall это неопределённое поведение. Для malloc такое утверждение ложно по определению.
const p = c.malloc(n).?; // asserts non-null
const q = c.malloc(n) orelse return error.OutOfMemory;
Вторая строка возвращает отказ вызывающему, и это честный вариант. С функциями, возвращающими [*c]u8, хуже, потому что в типе нет ?, который бы напомнил. Приведение C-указателя к неопциональному указателю - то же утверждение, только вообще без синтаксиса. Документация Zig называет нулевой адрес в этом месте недопустимым поведением с проверкой безопасности.
Поэтому в обёртках, которые я читаю, каждый C-указатель сначала проходит через опциональный тип, а orelse даёт ошибке имя. Чего я ещё не решил, так это какую ошибку. error.OutOfMemory подходит для malloc и не подходит для многих функций, которые возвращают null.