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

C语言从OBJ文件加载3个顶点值到char*数组时出现访问违规错误

解析OBJ文件时的访问违规错误排查与修复

我尝试实现一个函数读取OBJ文件,针对顶点行(以"v "开头)从第三个字符开始遍历提取坐标,但运行时出现访问违规错误。以下是我的代码:

bool LoadFromObjectFile(char* filepath) {
    FILE* pF;
    fopen_s(&pF, filepath, "r");
    if (pF == NULL)
        return false;

    char buffer[128];

    while (fgets(buffer, sizeof(buffer), pF) != NULL) {
        if (buffer[0] == 'v') {
            int currCoord = 0;
            char* vCoords[3] = { "", "", ""};

            for (int i = 2; i < sizeof(buffer); i++) {
                if (buffer[i] == ' ') {
                    currCoord++;
                    continue;
                }

                strcat_s(vCoords[currCoord], sizeof(&buffer[i]), &buffer[i]);
            }
        }
    }

    printf("%s\n", buffer);
    fclose(pF);

    return true;
}

错误原因分析

  • vCoords初始化错误:char* vCoords[3] = { "", "", ""}; 中每个元素指向的是只读内存中的字符串字面量,strcat_s试图修改只读内存直接触发访问违规,且字面量长度为0,没有空间容纳拼接内容。
  • strcat_s参数逻辑错误:第二个参数传sizeof(&buffer[i])是取指针的大小(通常4/8字节),不是目标缓冲区的可用大小;第三个参数传&buffer[i]会把从i位置开始的整个剩余字符串一次性拼入,而非单个字符,逻辑完全错误。
  • 循环边界错误:for (int i = 2; i < sizeof(buffer); i++) 会遍历缓冲区中未初始化的垃圾数据,可能导致越界访问。
  • 无边界检查:若顶点行空格数量超过2,currCoord会变成3,访问vCoords[3]触发数组越界。

修复后的代码

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

bool LoadFromObjectFile(char* filepath) {
    FILE* pF;
    if (fopen_s(&pF, filepath, "r") != 0 || pF == NULL) {
        return false;
    }

    char buffer[128];
    while (fgets(buffer, sizeof(buffer), pF) != NULL) {
        // 精准匹配顶点行,避免误判vn、vt等行
        if (buffer[0] == 'v' && buffer[1] == ' ') {
            // 给每个坐标分配可写缓冲区,预留足够空间
            char vCoords[3][32] = {0};
            int currCoord = 0;
            int charIndex = 0;
            
            // 仅遍历有效字符串内容
            for (int i = 2; buffer[i] != '\0'; i++) {
                if (buffer[i] == ' ') {
                    // 跳过连续空格
                    if (charIndex == 0) continue;
                    // 切换坐标前检查边界
                    if (currCoord < 2) {
                        currCoord++;
                        charIndex = 0;
                    }
                    continue;
                }
                // 防止缓冲区溢出
                if (charIndex < 31) {
                    vCoords[currCoord][charIndex++] = buffer[i];
                }
            }
            // 打印测试提取结果
            printf("顶点坐标:x=%s, y=%s, z=%s\n", vCoords[0], vCoords[1], vCoords[2]);
        }
    }

    fclose(pF);
    return true;
}

关键修复点

  • 将vCoords改为二维字符数组,提供可写内存空间,避免修改只读字面量。
  • 逐个字符写入目标缓冲区,替代错误的strcat_s调用,同时做溢出检查。
  • 循环终止条件改为buffer[i] != '\0',只处理有效字符串内容。
  • 增加连续空格跳过逻辑和currCoord边界检查,防止数组越界。
  • 完善顶点行判断条件,避免误处理法向量、纹理坐标等行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:22:09