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

SOCI/SQLite调用row.get<int64_t>时遇bad_cast或溢出问题求助

问题描述

我有一个基于C++的成熟项目,使用SOCI操作SQLite数据库,需要将较大的整数读取到64位整数类成员中,据我所知需要使用row.get<int64_t>(myvar)这类方式。

在Windows系统中,该显式模板get方法会抛出std::bad_cast异常;在Linux系统中,会出现int32溢出,返回值为-1。若将列类型改为BIGINT则可正常工作,但我不想这么做——我的所有值都在64位范围内。

最小可复现示例(MCVE)

#include <soci/soci.h>
#include <soci/sqlite3/soci-sqlite3.h>
#include <iostream>

int main() {
    try {
        // 创建内存中的SQLite数据库会话
        soci::session sql(soci::sqlite3, ":memory:");
        sql << "CREATE TABLE test_table (id INTEGER PRIMARY KEY, myInt INTEGER);";
        sql << "INSERT INTO test_table (myInt) VALUES (9223372036854775807);";

        // 此方式正常工作
        int64_t retrievedValue1;
        sql << "SELECT myInt FROM test_table WHERE id = 1", soci::into(retrievedValue1);
        std::cout << "隐式读取: " << retrievedValue1 << std::endl;

        // Windows下抛出std::bad_cast,Linux下int32溢出返回-1
        soci::row r;
        sql << "SELECT myInt FROM test_table WHERE id = 1", soci::into(r);
        int64_t retrievedValue2 = r.get<int64_t>("myInt");
        std::cout << "显式64位读取: " << retrievedValue2 << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
    }

    return 0;
}

环境配置

Windows/Visual Studio(vcpkg.json)

{
  "version": "1.0",
  "builtin-baseline": "c82f74667287d3dc386bce81e44964370c91a289",
  "dependencies": [
    {
      "name": "soci",
      "features": [
        "sqlite3"
      ]
    }
  ]
}

Linux(CMakeLists.txt,需将SOCI置于/usr/local/)

cmake_minimum_required(VERSION 3.10)
project(CppSQLiteSociExample)

# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 设置SOCI路径
set(SOCI_INCLUDE_DIR "/usr/local/include/soci")
set(SOCI_LIBRARY "/usr/local/lib/libsoci_sqlite3.so")

# 查找SQLite3包
find_package(SQLite3 REQUIRED)

# 检查SOCI头文件和库是否存在
if(NOT EXISTS "${SOCI_INCLUDE_DIR}/soci.h" OR NOT EXISTS "${SOCI_LIBRARY}")
    message(FATAL_ERROR "未找到SOCI库或头文件!")
endif()

# 添加源文件
add_executable(c c.cpp)

# 包含SOCI头文件并链接库
target_include_directories(c PRIVATE ${SOCI_INCLUDE_DIR})

target_link_libraries(c PRIVATE
    SQLite::SQLite3
    /usr/local/lib/libsoci_sqlite3.so
    /usr/local/lib/libsoci_core.so
)

# 确保链接器能找到库
link_directories(/usr/local/lib)

更新

已在GitHub的SOCI项目提交bug报告(编号1185)


解决方案

临时规避方案(无需修改数据库列类型)

  • 使用隐式读取替代显式row.get<int64_t>
    如示例中retrievedValue1的读取方式,直接通过soci::into(retrievedValue1)绑定int64_t变量,这种方式SOCI能正确处理SQLiteINTEGER类型的64位值,不会出现溢出或bad_cast问题。

  • 手动转换row中的值
    如果必须使用soci::row,可以先获取值的字符串表示,再转换为int64_t:

    std::string valStr = r.get<std::string>("myInt");
    int64_t retrievedValue2 = std::stoll(valStr);
    

    这种方式绕过SOCI的类型映射问题,直接从SQLite的字符串表示转换,适用于所有64位范围内的整数。

  • 修改SOCI的SQLite类型映射(进阶)
    可以自定义SOCI对SQLiteINTEGER类型的处理,强制将其映射为int64_t而非32位整数。需要修改SOCI的SQLite后端代码,调整类型转换逻辑,确保从SQLite读取INTEGER时优先按64位整数处理。

根本解决方向

由于该问题已提交为SOCI的bug,后续可关注SOCI项目的修复进展,待官方补丁发布后升级库版本即可彻底解决。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 16:40:58