我写了一个配置读取器,读取配置一切正常,但是在返回读取值(__getPath()函数调用了getByName()函数中循环体的chdBlock.begin()函数)报错分段异常Segmentation fault。
这段代码在windows系统上正常运行,但在linux系统上报错(肯定是在linux系统上编译的,系统CentOs x64)
我自己编写了一个List类,在这之前我使用的是std::list类,当然在使用过程中业报同样的错误。Segmentation fault
当然,我尝试过使用vector,又产生了新的错误:bad_alloc
本人技术略低,请忽略代码质量高低!
代码:
Config.h
#pragma once
#include <string.h>
namespace Lib {
int64_t str_to_num(const char* str) {
int res = 0;
int n_p = strlen(str);
int n_ten = 1;
while (n_p-- > 0) {
res += n_ten * (str[n_p] - '0');
n_ten *= 10;
}
return res;
}
bool str_to_bool(const char* str) {
if (strcmp(str, "true") == 0) return true;
return false;
}
}
#include <memory>
#include <stdint.h>
#include <vector>
#include "list.h"
#include <fstream>
#include <sstream>
class Config
{
public:
class ConfigBlock;
class ConfigItem {
private:
//state
bool is_blk;
std::string key;
ConfigBlock* owner;
protected:
ConfigItem(bool state, std::string t_key, ConfigBlock* own) :
is_blk(state), key(t_key), owner(own) { };
public:
bool isBlock() { return is_blk; }
bool isValue() { return !is_blk; }
std::string getName() const {
return key;
}
std::string setName(std::string n) {
std::string&& res = std::move(key);
key = n;
return res;
}
ConfigBlock* getOwner() const {
return owner;
}
};
class ConfigValue : public ConfigItem {
private:
struct eight_byte
{
int i1;
int i2;
};
public:
//用于类型识别
enum TypeEnum
{
Bool = 1,
String = 2,
Int = 3
};
private:
TypeEnum ty;
using INT = int64_t;
eight_byte val;
//用于与ConfigBlock的字节数保持一致
eight_byte pack[4];
public:
ConfigValue() : ConfigItem::ConfigItem(false, "", 0) { }
ConfigValue(TypeEnum type, ConfigBlock* owner, std::string name) : ty(type),
ConfigItem::ConfigItem(false, name, owner), val() { }
//类型判断
bool operator == (TypeEnum tyn) { return (ty == tyn); }
//获得值
std::string getStrDefault(std::string defVal = "") {
return
((ty == String) ? (*(std::string*)&val) : defVal);
}
INT getIntDefault(INT defVal = -1) {
return
((ty == Int) ? (*(INT*)&val) : defVal);
}
INT getBoolDefault(bool defVal = false) {
return
((ty == Bool) ? (*(bool*)&val) : defVal);
}
//返回类型
TypeEnum getType() { return ty; }
//设置值并返回原值
INT setValue(INT v) {
INT res = *((INT*)&val);
*((INT*)&val) = v;
return res;
}
//设置值并返回原值
std::string setValue(std::string v) {
std::string res = *((std::string*)&val);
new(&val) std::string(v);
return res;
}
//设置值并返回原值
bool setValue(bool v) {
bool res = *((bool*)&val);
*((bool*)&val) = v;
return res;
}
//设置类型并返回原类型(清空源数据)
TypeEnum setType(TypeEnum tye) {
TypeEnum t = ty;
ty = tye;
return t;
}
};
class ConfigBlock : public ConfigItem {
private:
//块的配置
List<ConfigValue> blockconf;
//子元素
List<ConfigValue> chdBlock;
public:
ConfigBlock() : ConfigItem::ConfigItem(true, "NULL", nullptr) { }
ConfigBlock(std::string bname, ConfigBlock* owner) :
ConfigItem::ConfigItem(true, bname, owner), blockconf(), chdBlock() { }
ConfigBlock(ConfigBlock&& blc) :
ConfigItem::ConfigItem(true, blc.getName(), blc.getOwner()) {
blockconf = blc.blockconf;
chdBlock = blc.chdBlock;
}
ConfigBlock(const ConfigBlock& blc) :
ConfigItem::ConfigItem(true, blc.getName(), blc.getOwner()) {
blockconf = blc.blockconf;
chdBlock = blc.chdBlock;
}
//添加配置
ConfigValue* addValueConfig(std::string kname, std::string v) {
blockconf.emplace_back(ConfigValue::String, this, kname);
ConfigValue* ptr = &blockconf.back();
ptr->setValue(v);
return ptr;
}
//添加配置
ConfigValue* addValueConfig(std::string kname, int64_t v) {
blockconf.emplace_back(ConfigValue::Int, this, kname);
ConfigValue* ptr = &blockconf.back();
ptr->setValue(v);
return ptr;
}
//添加配置
ConfigValue* addValueConfig(std::string kname, bool v) {
blockconf.emplace_back(ConfigValue::Bool, this, kname);
ConfigValue* ptr = &blockconf.back();
ptr->setValue(v);
return ptr;
}
//获取配置
ConfigValue* getConfByName(std::string keyname) {
for (List<ConfigValue>::ListIterator iter = blockconf.begin()
; (bool)iter; ++iter) {
if (iter->getName() == keyname) return iter.get();
}
return nullptr;
}
//通过名称获得键
ConfigItem* getByName(std::string keyname) {
for (List<ConfigValue>::ListIterator iter = chdBlock.begin()
; (bool)iter; ++iter) {
if (iter->getName() == keyname) return iter.get();
}
return nullptr;
}
//添加值
ConfigValue* addValue(std::string kname, std::string v) {
chdBlock.emplace_back(ConfigValue::String, this, kname);
ConfigValue* ptr = (ConfigValue*)&chdBlock.back();
ptr->setValue(v);
return ptr;
}
//添加值
ConfigValue* addValue(std::string kname, int64_t v) {
chdBlock.emplace_back(ConfigValue::Int, this, kname);
ConfigValue* ptr = (ConfigValue*)&chdBlock.back();
ptr->setValue(v);
return ptr;
}
//添加值
ConfigValue* addValue(std::string kname, bool v) {
chdBlock.emplace_back(ConfigValue::Bool, this, kname);
ConfigValue* ptr = (ConfigValue*)&chdBlock.back();
ptr->setValue(v);
return ptr;
}
//添加块
ConfigBlock* addBlock(std::string bname) {
chdBlock.emplace_back();
ConfigBlock* ptr = (ConfigBlock*)&chdBlock.back();
ptr = new(ptr) ConfigBlock(bname, this);
return ptr;
}
~ConfigBlock() {
}
};
public:
static std::shared_ptr<Config> readConfig(std::string confp);
private:
std::string errstr;
std::shared_ptr<ConfigBlock> root;
Config() : root(new ConfigBlock("root", nullptr)) { }
void readFailed(std::string why) { errstr = why; root.reset(); }
ConfigValue* __getPath(std::string& pth);
public:
//是否读取失败
bool failed() { return !errstr.empty(); }
//获得失败原因
std::string getFailedCause() { return errstr; }
//获得值
bool getBoolDefault(std::string path, bool def);
//获得值
std::string getStrDefault(std::string path, std::string def);
//获得值
int64_t getIntDefault(std::string path, int64_t def);
};
list.h
#pragma once
#include <string>
template <typename ty>
class List {
private:
struct Handler {
Handler* next;
Handler* last;
ty* ptvalue;
unsigned is_end : 1;
unsigned is_last : 1;
};
public:
class ListIterator {
friend class List;
private:
Handler* hdl;
ListIterator(Handler* hd) : hdl(hd) { }
public:
operator bool() {
return !(hdl->is_end || hdl->is_last);
}
ListIterator operator++() {
if (!hdl->is_end) {
hdl = hdl->next;
}
return *this;
}
ListIterator operator++(int) {
ListIterator lstI = *this;
if (!hdl->is_end) {
hdl = hdl->next;
}
return lstI;
}
ListIterator operator--() {
if (!hdl->is_last) {
hdl = hdl->last;
}
return *this;
}
ListIterator operator--(int) {
ListIterator lstI = *this;
if (!hdl->is_last) {
hdl = hdl->last;
}
return lstI;
}
ty* operator->() {
return hdl->ptvalue;
}
ty* get() {
return hdl->ptvalue;
}
};
private:
typedef List<ty>::Handler hdl;
hdl* fst_handler;
hdl* end_handler;
size_t siz = 0;
public:
List() {
fst_handler = new hdl;
end_handler = new hdl;
fst_handler->is_last = 1;
fst_handler->next = end_handler;
fst_handler->last = nullptr;
end_handler->last = fst_handler;
end_handler->next = nullptr;
end_handler->is_end = 1;
}
void push_back(ty& v) {
hdl* h = new hdl();
h->ptvalue = new ty(v);
h->last = end_handler->last;
h->next = end_handler;
end_handler->last = end_handler->last->next = h;
++siz;
}
void push_back(ty&& v) {
hdl* h = new hdl();
ty p = new ty(v);
h->ptvalue = &p;
h->last = end_handler->last;
h->next = end_handler;
end_handler->last = end_handler->last->next = h;
++siz;
}
void push_front(ty& v) {
hdl* h = new hdl();
h->ptvalue = new ty(v);
h->last = fst_handler;
h->next = fst_handler->next;
fst_handler->next = fst_handler->next->last = h;
++siz;
}
void push_front(ty&& v) {
hdl* h = new hdl();
h->ptvalue = new ty(v);
h->last = fst_handler;
h->next = fst_handler->next;
fst_handler->next = fst_handler->next->last = h;
++siz;
}
private:
void push_front(ty* v) {
hdl* h = new hdl();
h->ptvalue = v;
h->last = fst_handler;
h->next = fst_handler->next;
fst_handler->next = fst_handler->next->last = h;
++siz;
}
void push_back(ty* v) {
hdl* h = new hdl();
h->ptvalue = v;
h->last = end_handler->last;
h->next = end_handler;
end_handler->last = end_handler->last->next = h;
++siz;
}
public:
template<typename... argst>
void emplace_back(argst&&... ags) {
push_back(new ty(std::forward<argst>(ags)...));
}
template<typename... argst>
void emplace_front(argst&&... ags) {
push_front(new ty(std::forward<argst>(ags)...));
}
ListIterator begin() {
return ListIterator(fst_handler->next);
}
ListIterator end() { return ListIterator(end_handler->last); }
ty& front() { return *fst_handler->next->ptvalue; }
ty& back() { return *end_handler->last->ptvalue; }
ty& at(size_t index) {
if (index < 0 || index >= siz) throw 0;
hdl* hd = ((index < siz / 2) ? fst_handler.next : end_handler.last);
for (size_t i = 0; i < index; ++i) {
hd = ((index < siz / 2) ? hd.next : hd.last);
}
return *hd->ptvalue;
}
~List() {
hdl* hd = fst_handler;
hdl* nxt = nullptr;
for (int i = 0; i < siz; ++i) {
nxt = hd->next;
delete hd->ptvalue;
delete hd;
hd = nxt;
}
}
};
Config.cpp
#include "Config.h"
#include "lib_base.h"
std::shared_ptr<Config> Config::readConfig(std::string confp)
{
std::shared_ptr<Config> pConf = std::shared_ptr<Config>(new Config());
int npos = 0;
//读取文件
std::ifstream ifs(confp);
std::stringstream buffer;
buffer << ifs.rdbuf();
std::string file = buffer.str();
size_t filsiz = file.size();
std::vector<std::string> lines;
std::string n_file;
//对字符串变量
std::vector<std::string> strval;
ConfigBlock* fblo = pConf->root.get();
{
int llb = 0;
for (int bo = file.find('\"', 0), c = 0; bo != -1; bo = file.find('\"', bo), ++c) {
if (file[bo - 1] == '\\') {
++bo;
continue;
}
if (bo == -1) break;
int fd = file.find('\"', bo + 1);
r_rd:
if (file[fd - 1] == '\\') {
fd = file.find('\"', fd + 1);
goto r_rd;
}
if (fd == -1) {
pConf->readFailed("string not closed");
goto failed_rd;
}
strval.push_back(file.substr(bo + 1, fd - bo - 1));
n_file += file.substr(llb, bo - llb) + "$" + std::to_string(c);
llb = bo = fd + 1;
}
n_file += file.substr(llb);
file = std::move(n_file);
for (std::string& str : strval) {
for (int i = str.find_first_of('\\', 0); i != -1; i = str.find_first_of('\\', i)) {
char c_psb;
switch (str[i + 1])
{
case 'a':
c_psb = '\a';
break;
case 'b':
c_psb = '\b';
break;
case 'f':
c_psb = '\f';
break;
case 'n':
c_psb = '\n';
break;
case 'r':
c_psb = '\r';
break;
case 't':
c_psb = '\t';
break;
case 'v':
c_psb = '\v';
break;
case '\\':
c_psb = '\\';
break;
case '\?':
c_psb = '\?';
break;
case '\'':
c_psb = '\'';
break;
case '\"':
c_psb = '\"';
break;
case '0':
c_psb = '\0';
break;
default:
break;
}
str.erase(i, 1);
str[i] = c_psb;
}
}
}
//行分割
for (int i = 0; i < filsiz; ++i) {
int next = file.find_first_of(';', i);
if (next == -1) {
lines.push_back(file.substr(i));
break;
}
else {
lines.push_back(file.substr(i, next - i));
i = next;
}
}
//杀死所有空格
for (std::string& n_kill : lines) {
for (int i = 0; i < n_kill.size(); ++i) {
if (n_kill[i] == ' ' || n_kill[i] == '\n' || n_kill[i] == '\t')
n_kill.erase(i--, 1);
}
}
//进行处理
{
for (std::string& n_line : lines) {
if (n_line == "") continue;
re_do:
if (n_line[0] == '}') { n_line.erase(0, 1); fblo = fblo->getOwner(); }
//块判断
{
int blk_ps = n_line.find_first_of('<');
if (blk_ps != -1) {
//对config进行处理
int blk_psed = n_line.find_first_of('>');
if (blk_psed == -1) {
pConf->readFailed("Block config not closed");
goto failed_rd;
}
fblo = fblo->addBlock(n_line.substr(0, blk_ps));
int lst_f = 0;
//添加配置
for (int i = n_line.find_first_of(',', 0);
i != -1;
i = n_line.find_first_of(',', i)) {
std::string v = n_line.substr(lst_f, i - lst_f);
int equs = v.find_first_of('=');
std::string nm = v.substr(0, equs);
std::string vl = v.substr(equs + 1);
if (vl[0] >= '0' && vl[0] <= '9') {
fblo->addValueConfig(nm, Lib::str_to_num(vl.c_str()));
}
else if (vl[0] == '$') {
fblo->addValueConfig(nm, strval[vl[1] - '0']);
}
else if (vl == "true") {
fblo->addValueConfig(nm, true);
}
else if (vl == "false") {
fblo->addValueConfig(nm, false);
}
else {
pConf->readFailed("unknown value");
goto failed_rd;
}
lst_f = i + 1;
}
n_line = n_line.substr(blk_psed + 2);
goto re_do;
}
}
//值处理
{
int equs = n_line.find_first_of('=');
std::string nm = n_line.substr(0, equs);
std::string vl = n_line.substr(equs + 1);
if (vl[0] >= '0' && vl[0] <= '9') {
fblo->addValue(nm, Lib::str_to_num(vl.c_str()));
}
else if (vl[0] == '$') {
vl.erase(0, 1);
fblo->addValue(nm, strval[Lib::str_to_num(vl.c_str())]);
}
else if (vl == "true") {
fblo->addValue(nm, true);
}
else if (vl == "false") {
fblo->addValue(nm, false);
}
else {
pConf->readFailed("unknown value");
goto failed_rd;
}
}
}
}
failed_rd:
return pConf;
}
Config::ConfigValue* Config::__getPath(std::string& pth)
{
int64_t lst_ = 0;
ConfigBlock* prConf = root.get();
for (int64_t i = pth.find_first_of('/', 0); i != std::string::npos;
i = pth.find_first_of('/', lst_)) {
std::string next_go = pth.substr(lst_, i - lst_);
ConfigItem* cfgi = prConf->getByName(next_go);
if (cfgi == nullptr || cfgi->isValue()) return nullptr;
prConf = (ConfigBlock*)cfgi;
lst_ = i + 1;
}
std::string sname = pth.substr(lst_);
if (sname[0] == '~') {
sname.erase(0,1);
ConfigValue* cfgi = prConf->getConfByName(sname);
return cfgi;
}
ConfigItem* cfgi = prConf->getByName(sname);
if (cfgi == nullptr || cfgi->isBlock()) return nullptr;
return (ConfigValue*)cfgi;
}
bool Config::getBoolDefault(std::string path, bool def)
{
ConfigValue* cv = __getPath(path);
if (cv == nullptr) return def;
return cv->getBoolDefault(def);
}
std::string Config::getStrDefault(std::string path, std::string def)
{
ConfigValue* cv = __getPath(path);
if (cv == nullptr) return def;
return cv->getStrDefault(def);
}
int64_t Config::getIntDefault(std::string path, int64_t def)
{
ConfigValue* cv = __getPath(path);
if (cv == nullptr) return def;
return cv->getIntDefault(def);
}
Main.cpp
#include <unistd.h>
#include "Config.h"
int main(int argc, char** argv) {
const char* program_name = argv[0];
int a = sizeof(Config::ConfigBlock);
int b = sizeof(Config::ConfigValue);
std::shared_ptr<Config> cfg = Config::readConfig("./conf");
std::string str = cfg->getStrDefault("My_block/~stdc++","");
write(STDOUT_FILENO, "123", 3);
}
进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’
使用命令
gdb 运行程序名 core或core.数字
进入gdb然后使用bt命令
可以查看进程意外退出前函数调用的堆栈,内容为从上到下列出对应从里层到外层的函数调用历史。
如果进程意外退出不产生core文件,参考“ulimit -c core文件最大块大小”命令