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

C++读取配置文件遇未初始化内存及访问违规问题求助

问题描述

我正在编写一个读取配置文件并填充配置映射的类。读取文件时,使用指向enum class的指针触发了Access Violation,编译器提示使用未初始化内存。改成普通变量后,编译器仍提示变量未初始化,错误出现在conf_ptr相关逻辑上。


读取配置的函数代码

std::map<const char*, Config> conf_str_table = {
    { "screen_size", Config::screen_size },
    { "window_name", Config::window_name },
    { "cam_mov", Config::cam_mov },
};

void FileManager::GetConfigFromFile()
{
    std::ifstream* tmp = new std::ifstream(config_file_name);
    std::string* current_line = new std::string;
    std::pair<Config, std::string>* current_config = new std::pair<Config, std::string>;

    if (tmp->is_open()) {
        while (std::getline(*tmp, *current_line)) {

            // 忽略注释
            if (current_line->at(0) == '#')
                continue;

            bool is_reading_value = false;

            std::string* tmp_conf = new std::string;
            std::string* tmp_value = new std::string;

            for (auto c : *current_line) {

                if (c == ' ')
                    continue;

                if (c == '=') {
                    is_reading_value = true;
                    continue;
                }

                if (is_reading_value) {
                    tmp_value->push_back(c);
                } else {
                    tmp_conf->push_back(c);
                }
            }
            Config* conf_ptr = new Config;

            if (auto search = conf_str_table.find(tmp_conf->c_str()); search != conf_str_table.end()) {
                *conf_ptr = search->second;
            } else {
            }
            delete tmp_conf;
            current_config->first = *conf_ptr;
            current_config->second = *tmp_value;
            delete tmp_value;
        }
        delete current_line;
        delete current_config;
    } else {
        
    }
    delete tmp;
}

FileManager类定义

#pragma once

#include "raywin.h"
#include <fstream>
#include <map>
#include <raylib.h>
#include <vector>

constexpr const char* config_file_name = "config.cfg";

enum class Config {
    screen_size,
    window_name,
    cam_mov,
};

enum class Config_Error {
    property_not_found,
    config_file_not_found,
};

struct FileManager {
    /*
         禁止抛出异常!
         若发生错误,将加载默认设置并通知用户
 */
    void GetConfigFromFile();
    int GetInt(std::string& key);
    std::string GetString(std::string& key);
    double GetDouble(std::string& key);
    Vector2 GetVector2(std::string& key);
    void ErrorUseDefaultConfig(Config_Error& err);

private:
    std::map<Config, std::string> values = {
        { Config::screen_size, "1920x1080" },
        { Config::window_name, "Untitled" },
        { Config::cam_mov, "0.05" },
    };
};

问题根源与修复方案

1. 核心问题

  • 当配置名在conf_str_table中找不到时,conf_ptr指向的内存(或普通变量)未初始化,后续赋值会触发未定义行为,导致访问违规或编译器警告。
  • std::map<const char*, Config>以指针地址作为比较依据,tmp_conf->c_str()返回的临时指针与映射中字面量指针地址不匹配,导致合法配置名被误判为不存在,加剧未初始化问题。
  • 未检查空行,current_line.at(0)可能触发越界异常,违反“禁止抛出异常”的要求。
  • 大量不必要的动态内存分配,增加内存泄漏风险与代码复杂度。

2. 修复步骤

第一步:修正映射键类型,解决匹配问题

将conf_str_table的键改为std::string,按字符串内容匹配而非指针地址:

std::map<std::string, Config> conf_str_table = {
    { "screen_size", Config::screen_size },
    { "window_name", Config::window_name },
    { "cam_mov", Config::cam_mov },
};

查找时直接使用*tmp_conf:

if (auto search = conf_str_table.find(*tmp_conf); search != conf_str_table.end()) {
    // ...
}

第二步:兜底初始化,避免未定义行为

用普通变量替代指针,提前赋予默认枚举值,处理未找到配置的情况:

Config current_conf = Config::screen_size; // 赋默认值兜底
if (auto search = conf_str_table.find(tmp_conf); search != conf_str_table.end()) {
    current_conf = search->second;
} else {
    Config_Error err = Config_Error::property_not_found;
    ErrorUseDefaultConfig(err);
}
current_config.first = current_conf;

第三步:移除不必要的动态内存分配

改用栈变量,简化代码并避免内存泄漏:

void FileManager::GetConfigFromFile()
{
    std::ifstream tmp(config_file_name);
    std::string current_line;
    std::pair<Config, std::string> current_config;

    if (tmp.is_open()) {
        while (std::getline(tmp, current_line)) {
            // 先判断空行,避免越界
            if (current_line.empty() || current_line.at(0) == '#')
                continue;

            bool is_reading_value = false;
            std::string tmp_conf;
            std::string tmp_value;

            for (auto c : current_line) {
                if (c == ' ')
                    continue;
                if (c == '=') {
                    is_reading_value = true;
                    continue;
                }
                is_reading_value ? tmp_value.push_back(c) : tmp_conf.push_back(c);
            }

            Config current_conf = Config::screen_size;
            if (auto search = conf_str_table.find(tmp_conf); search != conf_str_table.end()) {
                current_conf = search->second;
            } else {
                Config_Error err = Config_Error::property_not_found;
                ErrorUseDefaultConfig(err);
            }
            // 将读取到的配置写入类的映射
            values[current_conf] = tmp_value;
        }
    } else {
        Config_Error err = Config_Error::config_file_not_found;
        ErrorUseDefaultConfig(err);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 22:22:03