← Revenir à la section Apprendre
This page was translated by the Zig community,
see the original version
or
report errors.
Exemples de code
Détection de fuites de mémoire
En utilisant std.heap.GeneralPurposeAllocator
vous pouvez trouver les libérations multiples de mémoire et les fuites.
leak.zig
const std = @import("std");
pub fn main() !void {
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(general_purpose_allocator.deinit() == .ok);
const gpa = general_purpose_allocator.allocator();
const u32_ptr = try gpa.create(u32);
_ = u32_ptr; // silences unused variable error
// oops I forgot to free!
}
$ zig build-exe leak.zig
$ ./leak
error(gpa): memory address 0x7f7eee02d000 leaked:
/home/runner/work/www.ziglang.org/www.ziglang.org/doctest-2e5f58c1/leak.zig:9:35: 0x1036290 in main (leak)
const u32_ptr = try gpa.create(u32);
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:511:37: 0x1036175 in posixCallMainAndExit (leak)
const result = root.main() catch |err| {
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:253:5: 0x1035c91 in _start (leak)
asm volatile (switch (native_arch) {
^
thread 2787 panic: reached unreachable code
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/debug.zig:403:14: 0x10364fd in assert (leak)
if (!ok) unreachable; // assertion failure
^
/home/runner/work/www.ziglang.org/www.ziglang.org/doctest-2e5f58c1/leak.zig:5:27: 0x10362f2 in main (leak)
defer std.debug.assert(general_purpose_allocator.deinit() == .ok);
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:511:37: 0x1036175 in posixCallMainAndExit (leak)
const result = root.main() catch |err| {
^
/home/runner/work/www.ziglang.org/www.ziglang.org/zig/lib/std/start.zig:253:5: 0x1035c91 in _start (leak)
asm volatile (switch (native_arch) {
^
???:?:?: 0x0 in ??? (???)
(process terminated by signal)
interopérabilité avec le C
Un exemple d’import d’en-tête C et de compilation avec à la fois la libc et la raylib.
// build with `zig build-exe cimport.zig -lc -lraylib`
const ray = @cImport({
@cInclude("raylib.h");
});
pub fn main() void {
const screenWidth = 800;
const screenHeight = 450;
ray.InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
defer ray.CloseWindow();
ray.SetTargetFPS(60);
while (!ray.WindowShouldClose()) {
ray.BeginDrawing();
defer ray.EndDrawing();
ray.ClearBackground(ray.RAYWHITE);
ray.DrawText("Hello, World!", 190, 200, 20, ray.LIGHTGRAY);
}
}
Zigg Zagg
Zig est optimisé pour les entretiens d’embauche demandant de comprendre du code (bon… peut-être pas vraiment).
zag.zig
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
var i: usize = 1;
while (i <= 16) : (i += 1) {
if (i % 15 == 0) {
try stdout.writeAll("ZiggZagg\n");
} else if (i % 3 == 0) {
try stdout.writeAll("Zigg\n");
} else if (i % 5 == 0) {
try stdout.writeAll("Zagg\n");
} else {
try stdout.print("{d}\n", .{i});
}
}
}
$ zig build-exe zag.zig
$ ./zag
1
2
Zigg
4
Zagg
Zigg
7
8
Zigg
Zagg
11
Zigg
13
14
ZiggZagg
16
Types génériques
Les types de Zig sont des valeurs à la compilation. Nous pouvons donc utiliser des fonctions qui retournent un type pour implémenter des algorithmes génériques et des structures de données. Dans l’exemple suivant nous implémentons une file générique et testons son comportement.
queue.zig
const std = @import("std");
pub fn Queue(comptime Child: type) type {
return struct {
const This = @This();
const Node = struct {
data: Child,
next: ?*Node,
};
gpa: std.mem.Allocator,
start: ?*Node,
end: ?*Node,
pub fn init(gpa: std.mem.Allocator) This {
return This{
.gpa = gpa,
.start = null,
.end = null,
};
}
pub fn enqueue(this: *This, value: Child) !void {
const node = try this.gpa.create(Node);
node.* = .{ .data = value, .next = null };
if (this.end) |end| end.next = node //
else this.start = node;
this.end = node;
}
pub fn dequeue(this: *This) ?Child {
const start = this.start orelse return null;
defer this.gpa.destroy(start);
if (start.next) |next|
this.start = next
else {
this.start = null;
this.end = null;
}
return start.data;
}
};
}
test "queue" {
var int_queue = Queue(i32).init(std.testing.allocator);
try int_queue.enqueue(25);
try int_queue.enqueue(50);
try int_queue.enqueue(75);
try int_queue.enqueue(100);
try std.testing.expectEqual(int_queue.dequeue(), 25);
try std.testing.expectEqual(int_queue.dequeue(), 50);
try std.testing.expectEqual(int_queue.dequeue(), 75);
try std.testing.expectEqual(int_queue.dequeue(), 100);
try std.testing.expectEqual(int_queue.dequeue(), null);
try int_queue.enqueue(5);
try std.testing.expectEqual(int_queue.dequeue(), 5);
try std.testing.expectEqual(int_queue.dequeue(), null);
}
$ zig test queue.zig
1/1 queue.test.queue... OK
All 1 tests passed.
Utiliser cURL depuis Zig
// compile with `zig build-exe zig-curl-test.zig --library curl --library c $(pkg-config --cflags libcurl)`
const std = @import("std");
const cURL = @cImport({
@cInclude("curl/curl.h");
});
pub fn main() !void {
var arena_state = std.heap.ArenaAllocator.init(std.heap.c_allocator);
defer arena_state.deinit();
const allocator = arena_state.allocator();
// global curl init, or fail
if (cURL.curl_global_init(cURL.CURL_GLOBAL_ALL) != cURL.CURLE_OK)
return error.CURLGlobalInitFailed;
defer cURL.curl_global_cleanup();
// curl easy handle init, or fail
const handle = cURL.curl_easy_init() orelse return error.CURLHandleInitFailed;
defer cURL.curl_easy_cleanup(handle);
var response_buffer = std.ArrayList(u8).init(allocator);
// superfluous when using an arena allocator, but
// important if the allocator implementation changes
defer response_buffer.deinit();
// setup curl options
if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_URL, "https://ziglang.org") != cURL.CURLE_OK)
return error.CouldNotSetURL;
// set write function callbacks
if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_WRITEFUNCTION, writeToArrayListCallback) != cURL.CURLE_OK)
return error.CouldNotSetWriteCallback;
if (cURL.curl_easy_setopt(handle, cURL.CURLOPT_WRITEDATA, &response_buffer) != cURL.CURLE_OK)
return error.CouldNotSetWriteCallback;
// perform
if (cURL.curl_easy_perform(handle) != cURL.CURLE_OK)
return error.FailedToPerformRequest;
std.log.info("Got response of {d} bytes", .{response_buffer.items.len});
std.debug.print("{s}\n", .{response_buffer.items});
}
fn writeToArrayListCallback(data: *anyopaque, size: c_uint, nmemb: c_uint, user_data: *anyopaque) callconv(.C) c_uint {
var buffer: *std.ArrayList(u8) = @alignCast(@ptrCast(user_data));
var typed_data: [*]u8 = @ptrCast(data);
buffer.appendSlice(typed_data[0 .. nmemb * size]) catch return 0;
return nmemb * size;
}