[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