You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zig代码运行Valgrind报非法硬件指令错误的原因及解决方法

Zig代码在Valgrind中运行报错的问题与解决

问题描述

尝试用Valgrind调试一段存在内存泄漏的Zig代码,代码如下:

const std = @import("std");

const Point = struct {
    x: i32,
    y: i32,
};

pub fn main() !void {
    const allocator = std.heap.c_allocator;
    const point = try allocator.create(Point);

    // defer allocator.destroy(point);

    point.* = Point{
        .x = 1234,
        .y = 5678,
    };

    std.debug.print("point={}\n", .{point});
}

编译命令:
zig build-exe leak.zig --library c
运行Valgrind命令:
valgrind ./leak
得到错误输出:

==21676== Memcheck, a memory error detector
==21676== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==21676== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==21676== Command: ./leak
==21676== 
point=leak.Point{ .x = vex amd64->IR: unhandled instruction bytes: 0x62 0xF2 0x7D 0x28 0x7A 0xC6 0xF 0x1F 0x44 0x0
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==21676== valgrind: Unrecognised instruction at address 0x25ca25.
==21676==    at 0x25CA25: memset (in /home/mattia/dev/test-zig/vv/leak)
==21676==    by 0x249C79: fmt.formatInt__anon_7676 (fmt.zig:1418)
==21676==    by 0x249BB3: fmt.formatIntValue__anon_7673 (fmt.zig:784)
==21676==    by 0x249B63: fmt.formatValue__anon_7672 (fmt.zig:733)
==21676==    by 0x243DBA: fmt.formatType__anon_7382 (fmt.zig:487)
==21676==    by 0x2382D7: fmt.formatType__anon_7092 (fmt.zig:596)
==21676==    by 0x22F46E: fmt.formatType__anon_6492 (fmt.zig:625)
==21676==    by 0x22F396: fmt.format__anon_6443 (fmt.zig:184)
==21676==    by 0x20C0E0: io.writer.Writer(fs.file.File,error{Unexpected,DiskQuota,FileTooBig,InputOutput,NoSpaceLeft,DeviceBusy,InvalidArgument,AccessDenied,BrokenPipe,SystemResources,OperationAborted,NotOpenForWriting,LockViolation,WouldBlock,ConnectionResetByPeer},(function 'write')).print__anon_4362 (writer.zig:28)
==21676==    by 0x20A0BD: debug.print__anon_3012 (debug.zig:90)
==21676==    by 0x209E35: leak.main (leak.zig:19)
==21676==    by 0x20A673: callMain (start.zig:608)
==21676==    by 0x20A673: initEventLoopAndCallMain (start.zig:542)
==21676==    by 0x20A673: callMainWithArgs (start.zig:492)
==21676==    by 0x20A673: main (start.zig:507)
==21676== Your program just tried to execute an instruction that Valgrind
==21676== did not recognise.  There are two possible reasons for this.
==21676== 1. Your program has a bug and erroneously jumped to a non-code
==21676==    location.  If you are running Memcheck and you just saw a
==21676==    warning about a bad jump, it's probably your program's fault.
==21676== 2. The instruction is legitimate but Valgrind doesn't handle it,
==21676==    i.e. it's Valgrind's fault.  If you think this is the case or
==21676==    you are not sure, please let us know and we'll try to fix it.
==21676== Either way, Valgrind will now raise a SIGILL signal which will
==21676== probably kill your program.

环境:Zig 0.11.0-dev.4006、Valgrind 3.21.0、Ubuntu 22.04

问:错误出现的原因是什么?如何在Zig代码上正常运行Valgrind?

错误原因

报错中提到的未识别指令是Zig默认编译时生成的AVX2指令集相关指令,而你使用的Valgrind 3.21.0对这类较新的指令集支持不完善,无法解析这些指令,因此触发SIGILL信号导致程序终止。

解决方法

1. 指定兼容指令集编译

编译时添加-march=x86-64参数,强制Zig生成基础x86-64指令集的代码,避免使用Valgrind不支持的新指令:

zig build-exe leak.zig --library c -march=x86-64

2. 验证内存泄漏

编译完成后重新运行Valgrind:

valgrind ./leak

此时程序能正常执行,Valgrind会正确检测到内存泄漏,输出类似如下的泄漏报告:

==XXXX== LEAK SUMMARY:
==XXXX==    definitely lost: 8 bytes in 1 blocks
==XXXX==    indirectly lost: 0 bytes in 0 blocks
==XXXX==      possibly lost: 0 bytes in 0 blocks
==XXXX==    still reachable: 0 bytes in 0 blocks
==XXXX==         suppressed: 0 bytes in 0 blocks

3. 可选:使用Zig内置内存调试工具

Zig本身提供了更贴合自身生态的内存调试方式,比如使用std.heap.GeneralPurposeAllocator并开启泄漏检测,无需依赖Valgrind:
修改代码如下:

const std = @import("std");

const Point = struct {
    x: i32,
    y: i32,
};

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const point = try allocator.create(Point);
    // defer allocator.destroy(point);

    point.* = Point{
        .x = 1234,
        .y = 5678,
    };

    std.debug.print("point={}\n", .{point});
}

编译运行后,程序退出时会自动输出内存泄漏信息:

point=main.Point{ .x = 1234, .y = 5678 }
error: memory leak detected
...

内容的提问来源于stack exchange,提问作者Isky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 00:54:57