Linux编程报错Segmentation fault

问题遇到的现象和发生背景

我写了一个配置读取器,读取配置一切正常,但是在返回读取值(__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);
}

img

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’
使用命令
gdb 运行程序名 core或core.数字
进入gdb然后使用bt命令
可以查看进程意外退出前函数调用的堆栈,内容为从上到下列出对应从里层到外层的函数调用历史。
如果进程意外退出不产生core文件,参考“ulimit -c core文件最大块大小”命令