我给你们弄了个假的复杂的。
我正在尝试开发一个使用INI配置文件的程序(我使用的是library库),如下所示:
[General]
output_directory = /scratch/miles/trans_assembly_pipeline/
[SRA accessions]
SRR18328591
SRR28481881它将其中的信息解析为映射,按节索引,然后按键进行索引,如下所示(唯一重要的位实际上是变量对象中的char*选项):
map<string, map<string, boost::variants<int, bool, double, string, char*>>因为INI文件中的键可以有各种类型,所以我使用Boost的“变体”库来允许多个值类型。最后,为了方便文件管理,我使用Boost的“文件系统”库。
我有一个INI解析实现文件,它基本上只是将INI数据存储到这样定义的映射类型中(仅包含函数声明和定义指令的标题可以在底部找到):
#include "ini_parse.h"
namespace fs = boost::filesystem;
// Dispatch INI data to a map, indexable by sections, then by keys
static int ini_callback(IniDispatch * const dispatch, void * map_pt) {
#define thismap (reinterpret_cast<INI_MAP*>(map_pt))
if (dispatch->type == INI_COMMENT) {
return 0;
}
if (dispatch->type == INI_SECTION) {
INI_MAP_ENTRY newSec;
thismap->insert(std::pair<std::string, INI_MAP_ENTRY>(dispatch->data, newSec));
return 0;
}
if (dispatch->type == INI_KEY) {
(*thismap)[dispatch->append_to].insert(std::pair<std::string, BOOST_VAR>(dispatch->data, dispatch->value));
}
return 0;
}
// Given a FILE object, return a buffer containing its contents
char * make_ini_buffer(FILE * iniFile) {
char * iniBuffer;
long sz;
fseek(iniFile, 0L, SEEK_END);
sz = ftell(iniFile);
rewind(iniFile);
iniBuffer = (char*)malloc(sz + 1);
fread(iniBuffer, 1, sz, iniFile);
return iniBuffer;
}
// Given the path/name of an INI config file, return a map of its data
// which can be indexed by sections, and then by keys
INI_MAP make_ini_map(const char * configPath) {
FILE * configIni = fopen(configPath, "r");
fs::path configPathObj(configPath);
try {
if (!configIni) {
std::string fileError = "ERROR: Cannot open config file: ";
throw std::runtime_error(fileError);
}
} catch (std::runtime_error& e){
std::cerr << e.what() << configPathObj.filename() << std::endl;
return {};
}
INI_MAP iniMap;
char * iniBuffer = make_ini_buffer(configIni);
strip_ini_cache(iniBuffer, strlen(iniBuffer), INI_DEFAULT_FORMAT,
NULL, ini_callback, &iniMap);
delete [] iniBuffer;
return iniMap;
}
INI_MAP cfgIni = make_ini_map("../config.ini");注意最后一行,在任何其他函数之外,定义'cfgIni‘。其想法是定义一个全局INI数据存储对象,它可以被其他文件外部使用--例如,如下所示:
#include "ini_parse.h"
int main() {
extern INI_MAP cfgIni;
extern int size_path;
std::cout << cfgIni["General"]["output_directory"] << std::endl;
return 0;
}现在是我的问题:在这个单独的文件中对外声明'cfgIni‘时,从在实现文件中定义它的位置到在外部声明它并在这里捕获内存似乎正在丢失。我没有问题访问父/子映射中的键,但是这些值更具有虚幻性。
当打印"General“部分的内容时,返回"output_directory”,没有问题。
我希望上面代码片段中的最后一行会打印filepath *数组,在INI文件中将"output_directory“设置为该数组。
然而,我却得到了一些随机字符,比如"�U“。更令人困惑的是,当我在内存中输出这个返回值的大小时,它会返回'40',这是该文件路径中正确的字符数。
我已经链接了我使用的库的文档和它们的功能。对这个问题的长度/复杂性表示歉意。
strip_ini_cache(): https://madmurphy.github.io/libconfini/html/confini_8c.html#a25d648d387f6e8bc36e7965accfca63b
Boost.variant: https://www.boost.org/doc/libs/1_61_0/doc/html/variant.html
Boost.filesystem: https://www.boost.org/doc/libs/1_80_0/libs/filesystem/doc/reference.html
下面是我的头文件:
#include <iostream>
#include <string>
#include <map>
#include <cstdio>
#include <confini.h>
#include <boost/filesystem.hpp>
#include <boost/variant.hpp>
#define BOOST_VAR boost::variant<int, bool, double, std::string, char*>
#define INI_MAP_ENTRY std::map<std::string, BOOST_VAR>
#define INI_MAP std::map<std::string, INI_MAP_ENTRY>
static int ini_callback(IniDispatch * const dispatch, void * map_pt);
char * make_ini_buffer(FILE * iniFile);
INI_MAP make_ini_map(const char * configPath);发布于 2022-09-30 02:58:23
这一问题的答案实在是微不足道。当通过值传递时,就像我在其中一个文件中所做的那样,创建了对象的一个浅拷贝,其中指向char数组的指针被野生地址覆盖。
解决办法是通过康斯特参考。
https://stackoverflow.com/questions/73902919
复制相似问题