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
相关产品推荐
相关产品推荐

