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

使用Ash映射vkDeviceMemory时触发STATUS_ACCESS_VIOLATION错误

问题描述

使用Rust的Vulkan绑定库Ash开发时,将自定义模型加载器输出的索引缓冲区数据写入vkDeviceMemory时,调用index_slice.copy_from_slice(&index_buffer_data)触发STATUS_ACCESS_VIOLATION(退出码0xc0000005)崩溃。硬编码顶点和索引数据时程序正常运行,仅加载模型数据时出现问题。

问题原因分析
  • 缓冲区大小计算错误:
    代码中用std::mem::size_of_val(&index_buffer_data)计算缓冲区大小,但index_buffer_data是Vec<u32>类型,size_of_val返回的是Vec结构体自身的内存占用(通常为24字节),而非内部存储的所有u32元素的总字节数。硬编码数组时size_of_val能正确返回数组总字节数,因此无问题;但加载模型得到的Vec会导致缓冲区和分配的内存远小于实际需要的大小,复制数据时越界访问内存,触发崩溃。
  • OBJ面数据解析逻辑存在缺陷:
    自定义模型加载器解析OBJ的f行时,直接将分割后的字符串整体解析为u32,但OBJ标准面格式通常是顶点索引/纹理坐标索引/法线索引(如1/2/3),这种情况下str.parse::<u32>()会解析失败,虽代码用unwrap()忽略错误,但会导致索引数据异常,是潜在的崩溃诱因。
  • Align结构体元素大小可能未正确初始化:
    copy_from_slice方法依赖self.elem_size == size_of::<T>() as u64判断是否启用批量复制,若Align::new时未将elem_size设置为size_of::<u32>() as u64,会退化为循环复制逻辑,结合内存大小计算错误,同样会引发越界访问。
解决办法
  • 修正缓冲区大小计算逻辑:
    将缓冲区创建和内存分配的大小改为基于Vec元素数量和单个元素大小的计算,替换原有的size_of_val调用:
    let index_buffer_create_info = vk::BufferCreateInfo {
        size: (index_buffer_data.len() * std::mem::size_of::<u32>()) as u64,
        usage: vk::BufferUsageFlags::INDEX_BUFFER,
        sharing_mode: vk::SharingMode::EXCLUSIVE,
        ..Default::default()
    };
    
    同步修改断言部分:
    assert_eq!(
        index_buffer_memory_req.size,
        (index_buffer_data.len() * std::mem::size_of::<u32>()) as u64
    );
    
  • 修复OBJ面数据解析逻辑:
    针对OBJ标准面格式,分割每个顶点的索引部分,提取顶点索引(第一个数值):
    "f" => {
        for face_part in line_split[1..] {
            let parts: Vec<&str> = face_part.split('/').collect();
            if let Some(vertex_idx_str) = parts.first() {
                let vertex_idx = vertex_idx_str.parse::<u32>().unwrap() - 1;
                index_buffer.push(vertex_idx);
            }
        }
    },
    
  • 确保Align结构体初始化正确:
    初始化Align时,将elem_size参数设置为std::mem::size_of::<u32>() as u64,保证批量复制的条件成立:
    let mut index_slice = Align::new(
        index_ptr,
        std::mem::align_of::<u32>() as u64,
        std::mem::size_of::<u32>() as u64,
        index_buffer_memory_req.size
    );
    
    (注:需根据Align结构体的实际定义调整参数顺序,确保elem_size被正确赋值)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 15:59:53