如何释放申请的内存问题? #123
Closed
zhang-chuanfeng
started this conversation in
General
Replies: 2 comments 4 replies
-
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer if (gpa.deinit() != .ok) @panic("leak");
const allocator = gpa.allocator();
const stdin = std.io.getStdIn();
var rdr = stdin.reader();
var list = std.ArrayList(u8).init(allocator);
defer list.deinit();
const wtr = list.writer();
while (rdr.streamUntilDelimiter(wtr, '\n', null)) {
if (std.mem.eql(u8, "exit", list.items)) {
return;
}
defer list.clearRetainingCapacity();
var iterator = std.mem.tokenizeAny(u8, list.items, "\t \r");
var args = std.ArrayList([]const u8).init(allocator);
defer args.deinit();
while (iterator.next()) |arg| {
try args.append(arg);
}
var cp = std.ChildProcess.init(args.items, allocator);
const term = cp.spawnAndWait();
std.debug.print("{any}\n", .{term});
} else |e| {
std.debug.print("Read stdin failed, err:{any}\n", .{e});
std.posix.exit(1);
}
}
尝试用纯 Zig 的方式来写,会简单不少,你现在的做法相当于完全 port C 的逻辑,很多 Zig 的特点没用上。 |
Beta Was this translation helpful? Give feedback.
2 replies
-
参考后修改: const std = @import("std");
fn signalHandler(sig: i32) align(1) callconv(.C) void {
std.debug.print("Received signal {}\n", .{sig});
std.os.linux.exit(-1);
}
fn signal(sig: u6, handler_fun: std.os.linux.Sigaction.handler_fn) void {
const sigAction = std.os.linux.sigaction;
var action = std.os.linux.Sigaction{ .handler = undefined, .mask = std.os.linux.empty_sigset, .flags = 0 };
action.handler.handler = handler_fun;
_ = sigAction(sig, &action, null);
}
pub fn main() !void {
signal(std.os.linux.SIG.INT, signalHandler);
std.debug.print("%% ", .{});
const allocator = std.heap.page_allocator;
const stdin = std.io.getStdIn().reader();
var pid: usize = undefined;
var status: u32 = undefined;
while (true) {
const line = try stdin.readUntilDelimiterAlloc(allocator, '\n', 1024);
pid = std.os.linux.fork();
if (pid < 0) {
std.debug.print("fork error", .{});
std.os.linux.exit(-1);
} else if (pid == 0) {
// child
const envp = [_:null]?[*:0]const u8{ "PATH=/usr/bin:/bin".ptr, null };
var tokenIter = std.mem.tokenize(u8, line, " \t\n\r");
// 使用ArrayList自动增长
var argvs = std.ArrayList([]const u8).init(allocator);
defer argvs.deinit();
while (tokenIter.next()) |token| {
try argvs.append(token);
}
// 这里参考 std.ChildProcess.spawnPosix()
// 使用allocSentinel 和 dupeZ
const argv_buf = try std.heap.page_allocator.allocSentinel(?[*:0]const u8, argvs.items.len, null);
defer std.heap.page_allocator.free(argv_buf);
for (argvs.items, 0..) |arg, i| argv_buf[i] = (try allocator.dupeZ(u8, arg)).ptr;
_ = std.os.linux.execve(argv_buf.ptr[0].?, argv_buf.ptr, &envp);
std.debug.panic("couldn't execute: {s}", .{line});
std.os.linux.exit(127);
}
pid = std.os.linux.waitpid(@intCast(pid), &status, 0);
if (pid < 0) {
std.debug.panic("waitpid fail", .{});
}
std.debug.print("%% ", .{});
}
// test execve()
// const args = [_:null]?[*:0]const u8{ "ls".ptr, "-l".ptr, "./".ptr, null };
// const envp = [_:null]?[*:0]const u8{null};
// _ = std.os.linux.execve("/usr/bin/ls".ptr, &args, &envp);
// std.os.linux.fork()
// std.time.sleep(100 * std.time.ns_per_hour);
} |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
如下代码实现fork执行exec程序代码:中间申请的buff如何释放掉?怎么感觉写起来没这么方便,应该有更好的实现方式吧?感觉比c写的代码要繁琐
比如下面的执行结果:
c的代码实现
Beta Was this translation helpful? Give feedback.
All reactions