【问题标题】:weird - mysql's sql::SQLException is not caught by its type, but is caught as std::exception and cast back successfully奇怪 - mysql 的 sql::SQLException 没有被它的类型捕获,而是被捕获为 std::exception 并成功回滚
【发布时间】:2025-11-20 16:00:03
【问题描述】:

我正在使用带有这个(有点简化的)代码的 mysql c++ 连接器。

try
{
    statement->setString(1, word);
    statement->executeUpdate();
}
catch( sql::SQLException& e )
{
    // I don't get here
    return sqlerrno_to_error_code( e.getErrorCode() );
}
catch( std::exception& e )
{
    // I do get here and the cast works
    sql::SQLException& sqle = (sql::SQLException&) e;
    return sqlerrno_to_error_code( sqle.getErrorCode() );
}

连接器应该抛出派生自 std::exception 的 sql::SQLException 并具有一些附加方法,例如 getErrorCode()

引发的异常在第二个catch 块中被捕获,但可以成功转换为(并用作)sql::SQLException

更奇怪的是,不同可执行文件中的类似代码按预期捕获sql::SQLException。它们之间的区别在于第一个是在一个共享对象 (.so) 中,它加载了dlopen()

RHEL 5.7 32 位,gcc 4.1.2

【问题讨论】:

    标签: c++ mysql linux exception shared-libraries


    【解决方案1】:

    请参阅 GCC 常见问题页面上的 dynamic_cast, throw, typeid don't work with shared libraries 注释。

    因为您使用的是dlopen(),所以您需要使用-E 标志链接您的可执行文件(或者如果g++ 正在调用链接器,则将-Wl,-E 传递给g++)并传递@987654331 @ 标志为dlopen()

    【讨论】:

    • 谢谢,同时找到了它,但到目前为止似乎没有帮助。它可能取决于编译器版本吗?我的是 4.1.2
    • @davka:问题可能是使用了不同的编译器来编译 MySQL Connector/C++ 库,因为编译器 ABI 是特定于实现的。尝试使用相同的编译器从源代码重新编译连接器/C++ 库(转到dev.mysql.com/downloads/connector/cpp 并从平台组合框中选择“源代码”)。
    • 好点。我不认为我们可以重新编译连接器 - 我们要求客户端安装 mysqll 作为 pre-req,但值得检查它是用哪个版本编译的
    • @davka:您确定不能重新编译连接器/C++ 库并将自定义构建的库与您的可执行文件一起分发吗?我不相信 Connector/C++ 是随 MySQL 一起安装的,无论如何,您可以将链接器配置为链接到相对路径,依靠 /lib/ld-linux.so 的 $ORIGIN/rpath 支持来确保您的自定义-使用了内置的 Connector/C++ 库。
    • 你是对的,它不是。这实际上是一个法律问题 - 即使客户是购买许可证的人,我们是否可以分发它。
    最近更新 更多