[odb-users] Segmentation fault (core dumped)

ShuRan Song songshuran4 at gmail.com
Sun Jul 12 12:19:02 EDT 2026


#pragma once
#include <iostream>
#include <string>
#include <cstddef>
#include <odb/core.hxx>
#include <odb/nullable.hxx>

namespace ssr_im
{
#pragma db object table("user")
    class User
    {
    public:
        User() {};
        User(std::string uid, std::string nickname, std::string password) :
_user_id(uid), _nickname(nickname), _password(password) {}
        User(const std::string uid, const std::string phone) : _user_id(uid
), _nickname(uid), _phone(phone) {}

        void user_id(const std::string &val) { _user_id = val; }
        std::string user_id() { return _user_id; }

        std::string nickname()
        {
            if (_nickname)
                return *_nickname;
            return std::string();
        }
        void nickname(const std::string &val) { _nickname = val; }

        std::string description()
        {
            if (!_description)
                return std::string();
            return *_description;
        }
        void description(const std::string &val) { _description = val; }

        std::string password()
        {
            if (!_password)
                return std::string();
            return *_password;
        }
        void password(const std::string &val) { _password = val; }

        std::string phone()
        {
            if (!_phone)
                return std::string();
            return *_phone;
        }
        void phone(const std::string &val) { _phone = val; }

        std::string avatar_id()
        {
            if (!_avatar_id)
                return std::string();
            return *_avatar_id;
        }
        void avatar_id(const std::string &val) { _avatar_id = val; }

    private:
        friend class odb::access;
#pragma db id auto
        unsigned long _id; // 主键id
#pragma db type("varchar(64)") index unique
        std::string _user_id; // 用户id
#pragma db type("varchar(64)") index unique
        odb::nullable<std::string> _nickname; // 用户昵称-不一定存在,因为手机号注册时不需要昵称
#pragma db type("varchar(64)")
        odb::nullable<std::string> _description; // 用户签名-不一定存在
#pragma db type("varchar(64)")
        odb::nullable<std::string> _password; // 用户密码-不一定存在,因为手机号注册时不需要密码
#pragma db type("varchar(64)") index unique
        odb::nullable<std::string> _phone; // 用户手机号-不一定存在
#pragma db type("varchar(64)")
        odb::nullable<std::string> _avatar_id; // 用户头像文件id-不一定存在
    };
}

//  odb -d mysql --generate-query --generate-schema ../../odb/user.hxx
// odb -d mysql  --generate-query --generate-schema --profile
boost/date-time ../../odb/user.hxx







#include <iostream>
#include <memory>
#include <odb/mysql/database.hxx>
#include <odb/transaction.hxx>
#include "../../odb/user.hxx"
#include "../test/user-odb.hxx"
#include <gflags/gflags.h>
#include "../../common/logger.hpp"
#include <sstream>
#include <vector>

namespace ssr_im
{
    class OBDFactory
    {
    public:
        static std::shared_ptr<odb::core::database> create(std::string user,
std::string pswd, std::string host, int port,
                                                           std::string db,
int max_pool, std::string cset)
        {
            std::shared_ptr<odb::mysql::database> str;
            // 1. 构造连接池工厂配置对象
            std::unique_ptr<odb::mysql::connection_pool_factory> cpf(new odb
::mysql::connection_pool_factory(max_pool, 0));
            // 2. 构造数据库操作对象:MySQL用户名 MySQL密码 数据库名称 MySQL服务器地址 MySQL端口
socket文件路径 字符集 MySQL客户端标志位 连接池工厂对象
            // str = std::make_shared<odb::mysql::database>(user, pswd, db,
host, port, "", cset, 0, std::move(cpf));
            str = std::make_shared<odb::mysql::database>(user, pswd, db,
host, port, nullptr, cset, 0, std::move(cpf));
            return str;
        }
    };

    class UserTable
    {
    public:
        UserTable(std::shared_ptr<odb::core::database> &db) : _db(db) {}
        // 插入用户数据
        bool insert(const std::shared_ptr<ssr_im::User> &user)
        {
            try
            {
                odb::transaction trans(_db->begin());
                _db->persist(*user);
                trans.commit();
            }
            catch (std::exception &e)
            {
                LOG_ERR("新增用户{}失败 :{}", user->nickname(), e.what());
                return false;
            }
            return true;
        }

        // 删除用户
        // bool del(const std::shared_ptr<ssr_im::User> &user)
        // {
        //     try
        //     {
        //         odb::transaction trans(_db->begin());
        //         // shared_ptr 自己重载了
operator*(),所以实际上会调用:user.operator*();返回 User&。
        //         _db->erase(*user);
        //         // 这个get是返回 shared_ptr 内部管理的裸指针(User*),不会创建新的对象,也不会转移所有权。
        //         // _db->erase(*(user.get()));
        //         trans.commit();
        //     }
        //     catch (std::exception &e)
        //     {
        //         LOG_ERR("删除用户{}失败 :{}", user->nickname(), e.what());
        //         return false;
        //     }
        //     return true;
        // }

        bool update(const std::shared_ptr<ssr_im::User> &user)
        {
            try
            {
                odb::transaction trans(_db->begin());
                _db->update(*user);
                trans.commit();
            }
            catch (std::exception &e)
            {
                LOG_ERR("更新用户{}失败 :{}", user->nickname(), e.what());
                return false;
            }
            return true;
        }

        std::shared_ptr<ssr_im::User> select_by_nickname(const std::string &
nickname)
        {
            std::shared_ptr<ssr_im::User> str;
            try
            {
                /* code */
                odb::transaction trans(_db->begin());
                typedef odb::query<ssr_im::User> query;
                typedef odb::result<ssr_im::User> result;
                // query() 返回 odb::result<T>
且query是查询多个,若有多个同名全部返回出来,通过迭代器取出
                // query_one() 不返回 odb::result<T> query_one()
的返回类型User*。用来查询唯一,也只会返回一个
                str.reset(_db->query_one<ssr_im::User>(query::nickname ==
nickname));
                trans.commit();
            }
            catch (const std::exception &e)
            {
                LOG_ERR("根据用户名查询{}失败 :{}", nickname, e.what());
            }
            return str;
        }

        std::shared_ptr<ssr_im::User> select_by_phone(const std::string &
phone)
        {
            std::shared_ptr<ssr_im::User> str;
            try
            {
                /* code */
                odb::transaction trans(_db->begin());
                typedef odb::query<ssr_im::User> query;
                typedef odb::result<ssr_im::User> result;
                str.reset(_db->query_one<ssr_im::User>(query::phone == phone
));
                trans.commit();
            }
            catch (const std::exception &e)
            {
                LOG_ERR("根据手机号查询{}失败 :{}", phone, e.what());
            }
            return str;
        }

        std::shared_ptr<ssr_im::User> select_by_user_if(const std::string &
user_id)
        {
            std::shared_ptr<ssr_im::User> str;
            try
            {
                /* code */
                odb::transaction trans(_db->begin());
                typedef odb::query<ssr_im::User> query;
                typedef odb::result<ssr_im::User> result;
                str.reset(_db->query_one<ssr_im::User>(query::user_id ==
user_id));
                trans.commit();
            }
            catch (const std::exception &e)
            {
                LOG_ERR("根据用户id号查询{}失败 :{}", user_id, e.what());
            }
            return str;
        }

        // 多user_id查询,返回多个用户
        std::vector<ssr_im::User> select_multi_users(const std::vector<std::
string> &id_list)
        {
            // select * from user where id in ('id1', 'id2', ...)
            if (id_list.empty())
            {
                return std::vector<ssr_im::User>();
            }
            std::vector<ssr_im::User> res;
            try
            {
                odb::transaction trans(_db->begin());
                typedef odb::query<ssr_im::User> query;
                typedef odb::result<ssr_im::User> result;
                std::stringstream ss;
                ss << "user_id in (";
                for (const auto &id : id_list)
                {
                    ss << "'" << id << "',";
                }
                std::string condition = ss.str();
                condition.pop_back();
                condition += ")";
                result r(_db->query<ssr_im::User>(condition));
                for (result::iterator i(r.begin()); i != r.end(); ++i)
                {
                    res.push_back(*i);
                }
                trans.commit();
            }
            catch (std::exception &e)
            {
                LOG_ERR("通过用户ID批量查询用户失败:{}!", e.what());
            }
            return res;
        }

    private:
        std::shared_ptr<odb::core::database> _db;
    };
}




#include "user-odb.hxx"
// #include "../../odb/user.hxx"
#include "../../common/logger.hpp"
#include "../source/mysql_user.hpp"

DEFINE_bool(run_mode, false, "程序的运行模式,false-调试; true-发布;");
DEFINE_string(log_file, "", "发布模式下,用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下,用于指定日志输出等级");

void insert(ssr_im::UserTable &user)
{
    auto u1 = std::make_shared<ssr_im::User>("user1", "lxr", "123456");
    auto u2 = std::make_shared<ssr_im::User>("user2", "ayq", "888888");
    bool ret = user.insert(u1);
    if (!ret)
    {
        std::cout << "插入错误" << std::endl;
    }
    ret = user.insert(u2);
    if (!ret)
    {
        std::cout << "插入错误" << std::endl;
    }
}

int main(int argc, char *argv[])
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    ssr_im::init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    auto db = ssr_im::OBDFactory::create("root", "123456", "127.0.0.1", 3306
, "ssr_im", 1, "utf8");
    ssr_im::UserTable users(db);
    insert(users);
    // odb::mysql::database db("root", "123456", "ssr_im", "127.0.0.1",
3306);
    // odb::transaction t(db.begin());
    // std::cout << "begin ok" << std::endl;
    // t.commit();
    // std::cout << "commit ok" << std::endl;
}

半年前我还能运行,现在一运行就是Segmentation fault (core dumped),说是
_db->persist(*user);
这里的问题,空指针


More information about the odb-users mailing list