Freeing the Linux Auxiliary Vector
Status quo
When you launch a Linux program, it inherits a full copy of the entire environment, arguments, and various other things into its memory, for its entire life. This is typically a 4K page, and on the particularly bad Ubuntu more like two pages. Type this into a terminal to see the size of the environment portion.
env | wc -c
ARGV[0]
is in there twice (AT_EXECFN
which the caller cannot modify, and ARGV[0]
which the caller can specify, and whose value is only customary), for the entire life-time of the every program. The aux vector can be giant, and this is completely out of the application's control. The minimum upper-bound is 128KiB, and since Linux 2.6.23 is raised to 1/4 of the stack size. This means that to avoid undefined stack overflow your program has to calculate that it can only use 3/4 of the stack!
Proposal
const bootstrap = @import("std").bootstrap;
pub fn init() void {
// parse arguments, environment, and auxilery vector,
// putting anything needed into global variables[1]
}
bootstrap.init = init; // This enables the feature.
pub fn main() void {
// The frame pointer is guaranteed to point to the edge
// of the stack's memory
}
Why
- Less memory usage.
- Predictable memory usage:
main
's stack is always at the edge of the allocation - Separates parsing of user input from the logic of the program (think Model-View-Controller)
- No need to assure use of only 3/4 of stack
- Actually (with the rest of Zig) possible to write an application that can gracefully handle out-of-memory conditions
[1] Global variables are namespaced in Zig, and while they need to be used carefully in shared libraries, the do not have the same problems as global variables in C.