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

使用Zig的@fieldParentPtr时触发死锁检测错误的解决

在Zig中模拟接口行为时的死锁问题及解决方法

我尝试在Zig语言中通过技巧实现接口行为,编写示例代码期望调用Animal结构体的函数时访问Dog结构体的属性。虽然能成功获取name属性的值,但在std.debug.print中使用该值时触发了死锁检测错误。

错误信息片段

thread 17672 panic: Deadlock detected
C:\Software\Zig\Zig12Dev\zig\lib\std\Thread\Mutex.zig:45:19: 0xde2de4 in lock (zoo_example.exe.obj)
    self.impl.lock();
                  ^
C:\Software\Zig\Zig12Dev\zig\lib\std\debug.zig:85:22: 0xde34cb in print__anon_7068 (zoo_example.exe.obj)
    stderr_mutex.lock();
                     ^
C:\Software\Zig\Zig12Dev\zig\lib\std\os\windows.zig:2688:24: 0xdb234f in unexpectedError (zoo_example.exe.obj)
        std.debug.print("error.Unexpected: GetLastError({}): {}\n", .{
....
....

原问题代码

const std = @import("std");
      
const Animal = struct{
    walkfn : *const fn(*const Animal,u32) anyerror!void,
    fn walk(self:*const Animal,speed:u32) !void{
        return self.walkfn(self,speed);
    }
};
      
const Dog = struct{
    animal:Animal = Animal{.walkfn = walk},
    name:[]const u8,
    fn walk(animal:*const Animal,speed:u32) !void{  
        const self = @fieldParentPtr(Dog,"animal",animal);
        const _name = self.name;
        std.debug.print("{s} is walking with {d} miles/hr\n",.{_name,speed});
    }
};
  
const Cat = struct{
    animal:Animal = Animal{.walkfn = walk},
    fn walk(_:*const Animal,speed:u32) !void{
        std.debug.print("cat is walking with {d} miles/hr\n",.{speed});
    }
};

      
pub fn main() !void{
    const animals:[2]Animal = [_]Animal{(Dog{.name="Buddy"}).animal,(Cat{}).animal};
    for (animals) |animal|{
        try animal.walk(12);
    }
}

问题原因及解决方案

原代码的核心问题在于:创建animals数组时,Dog{.name="Buddy"}是临时值,其生命周期仅存在于数组初始化的瞬间,后续访问该临时值的属性会导致未定义行为,进而触发死锁。

正确的实现方式是通过*anyopaque存储具体类型的指针,同时保证具体实例的生命周期覆盖整个使用过程。以下是可行的解决方案代码:

const std = @import("std");
      
const Animal = struct{
    ptr: *anyopaque,
    walkfn: *const fn(ptr:*anyopaque,speed:u32) anyerror!void,
          
    fn walk(animal:Animal,speed:u32) !void{
        try animal.walkfn(animal.ptr,speed);
    }
};
      
      
const Dog = struct{
    age:u32,
              
    fn walk(ptr:*anyopaque,speed:u32) !void{
        const self:*Dog = @ptrCast(@alignCast(ptr));
        std.debug.print("dog is {d} years old and is walking with speed {d}\n",.{self.age,speed});
    }
          
    fn animal(self:*Dog) Animal{
        return .{.ptr = self, .walkfn = walk};
    }
};

const Cat = struct{
    color:[]const u8,
    
    fn walk(ptr:*anyopaque,speed:u32) !void{
        const self:*Cat = @ptrCast(@alignCast(ptr));
        std.debug.print("cat with color {s} is walking with speed {d}\n",.{self.color,speed});
    }
    
    fn animal(self:*Cat) Animal{
        return .{.ptr = self,.walkfn = walk};
    }
};

const AnimalWalker = struct{
    fn walk(animal:Animal) !void{
        try animal.walk(20);
    }
};
      
pub fn main() !void{
    var dog = Dog{.age=12};
    var cat = Cat{.color="grey"};
    const animals:[2]Animal = [_]Animal{dog.animal(),cat.animal()};
    for (animals) |animal|{
        try animal.walk(123);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:23:20