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

VS2015中使用Berkeley DB STL的dbstl::db_map<string, list<string>>报错解决

使用Berkeley DB STL时list作为db_map值类型触发断言失败的解决方法

在Visual Studio 2015环境下使用Berkeley DB STL库,尝试将list<string>作为dbstl::db_map的value类型时运行报错,触发“list iterator not dereferencable”等断言失败问题,以下是代码、错误详情及解决方案:

问题代码

#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "libdb181.lib")
#pragma comment(lib, "libdb_stl181.lib")

#include "stdafx.h"
#include <iostream>
#include <dbstl_map.h>
#include <list>
using namespace std;

int main(){
    const char* db_name = "db";
    const char* db_home_dir = "dbdir";

    DbEnv env(DB_CXX_NO_EXCEPTIONS);
    Db* pdb;

    try {
        dbstl::dbstl_startup();

        env.set_error_stream(&cerr);
        env.open(db_home_dir, DB_CREATE | DB_INIT_MPOOL, 0);

        pdb = new Db(&env, DB_CXX_NO_EXCEPTIONS);
        pdb->open(NULL, db_name, NULL, DB_BTREE, DB_CREATE, 0);

        typedef dbstl::db_map<string, list<string>> dbmap_list;
        dbmap_list map_list(pdb, &env);

        string key_list = "list";
        list<string> value_list;
        value_list.push_back("first"); value_list.push_back("second");
        map_list.insert({ key_list, value_list });
        
        list<string> outvalue_list = map_list[key_list];
        list<string>::iterator it = outvalue_list.begin();
        cout << *it;

        dbstl::dbstl_exit();

        if (pdb != NULL) {
            pdb->close(0);
            delete pdb;
        }
        env.close(0);

    }
    catch (DbException& e) {
        cerr << "DbException: " << e.what() << endl;
        _sleep(5000);
        return -1;
    }
    catch (std::exception& e) {
        cerr << e.what() << endl;
        _sleep(5000);
        return -1;
    }

    cout << "hello";
    _sleep(5000);
    return 0;
}

错误信息

程序: C:\Windows\SYSTEM32\MSVCP140D.dll
文件: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\list
行: 211
表达式: list iterator not dereferencable
有关程序如何导致断言失败的信息,请查看 Visual C++ 文档中的断言说明。
(按重试调试应用程序) ConsoleApplication8.exe 触发了断点。

调试断言失败!
程序: ..._V36\p1\ConsoleApplication8\x64\Debug\ConsoleApplication8.exe
文件: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\list
行: 212
表达式: "Standard C++ Libraries Out of Range" && 0
有关程序如何导致断言失败的信息,请查看 Visual C++ 文档中的断言说明。
(按重试调试应用程序)
'ConsoleApplication8.exe' (Win32): 已加载 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Debugger.Runtime\14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Debugger.Runtime.dll'。
'ConsoleApplication8.exe' (Win32): 已卸载 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Debugger.Runtime\14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Debugger.Runtime.dll'
'ConsoleApplication8.exe' (CLR v4.0.30319: ConsoleApplication8.exe): 已加载 'C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Debugger.Runtime\14.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Debugger.Runtime.dll'。
在 ConsoleApplication8.exe 中的 0x00007FFB60CF10CB (ucrtbased.dll) 处发生未处理的异常: 传递给考虑无效参数为致命错误的函数的参数无效。

原因及解决方法

问题根源

DBSTL的默认序列化机制对std::list的支持存在缺陷:std::list是链表结构,其迭代器依赖内部节点的内存地址,反序列化后链表的节点地址发生变化,导致迭代器失效;同时默认序列化可能未正确还原std::list的内部状态,读取后得到空链表,进而触发“迭代器不可解引用”的断言。

方案1:改用std::vector替代std::list

std::vector是连续内存结构,DBSTL的默认序列化逻辑能正确处理其内存布局,不会出现迭代器失效问题。修改代码如下:

// 替换list为vector
typedef dbstl::db_map<string, vector<string>> dbmap_list;

// 对应value类型也修改
vector<string> value_list;
value_list.push_back("first"); value_list.push_back("second");
map_list.insert({ key_list, value_list });

auto it_map = map_list.find(key_list);
if (it_map != map_list.end()) {
    vector<string> outvalue_list = it_map->second;
    if (!outvalue_list.empty()) {
        cout << outvalue_list[0];
    }
}

方案2:为std::list实现自定义序列化/反序列化

通过特化dbstl::db_serializer模板,手动实现std::list<string>的序列化和反序列化逻辑,确保数据正确存储和还原:

#include <cstring>

namespace dbstl {
    template<>
    class db_serializer<list<string>> {
    public:
        static void serialize(const list<string>& obj, Dbt& dbt) {
            // 计算总字节数:每个字符串存长度(size_t)+ 内容
            size_t total_size = 0;
            for (const auto& s : obj) {
                total_size += sizeof(size_t) + s.size();
            }

            // 分配内存并写入数据
            char* buf = new char[total_size];
            char* ptr = buf;
            for (const auto& s : obj) {
                size_t len = s.size();
                memcpy(ptr, &len, sizeof(len));
                ptr += sizeof(len);
                memcpy(ptr, s.c_str(), len);
                ptr += len;
            }

            // 设置Dbt,让DB负责释放内存
            dbt.set_data(buf);
            dbt.set_size(total_size);
            dbt.set_flags(DB_DBT_APPMALLOC);
        }

        static void deserialize(Dbt& dbt, list<string>& obj) {
            obj.clear();
            char* ptr = static_cast<char*>(dbt.get_data());
            size_t remaining = dbt.get_size();

            // 逐个读取字符串
            while (remaining > 0) {
                size_t len;
                memcpy(&len, ptr, sizeof(len));
                ptr += sizeof(len);
                remaining -= sizeof(len);

                string s(ptr, len);
                obj.push_back(s);

                ptr += len;
                remaining -= len;
            }
        }
    };
}

额外注意事项

  • 避免直接使用map_list[key_list]:若key不存在,该操作会默认构造空的list<string>,增加出错风险。建议先用find检查key是否存在,再访问对应value。
  • 确保Berkeley DB与DBSTL版本匹配:代码中使用的是18.1版本,需保证库文件libdb181.lib、libdb_stl181.lib与头文件版本一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:01:01