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

C++调用LevelDB PUT接口存储大文件时触发abort() has been called错误

LevelDB 调用Put触发abort问题排查

问题根因

你遇到的abort报错和LevelDB本身的配置、大小限制无关,完全是代码bug导致的非法内存访问触发的系统级中断,具体错误点如下:

  • 内存越界:你用calloc(1, size)申请了size字节的缓冲区,构造Slice时却传入了size + 1的长度,会导致LevelDB读取缓冲区外的非法内存
  • 野指针访问:构造key对应的Slice时,你直接将char类型的key值(ASCII码0x31)作为指针传入,相当于直接访问内存地址0x31,属于典型的野指针访问
  • 参数传错:调用Put接口时你传入的是char类型的key,而不是你构造的key_in,进一步放大了野指针问题
  • 变量名不匹配:DB::Open的返回值赋值给了s,后续assert却用了未赋值的status,导致Open阶段的错误没有被捕获
  • 语法错误:woptions.sync = true' 末尾错写为单引号,key.clear()针对char类型调用不存在的方法,编译阶段就应该报错

修正方案

修正后的可运行代码如下:

FILE* file;
WriteOptions woptions;
woptions.sync = true;
DB* db;
Options options;
options.create_if_missing = true;

std::string DBPATH(DBName);
const char key_char = '1';

Status s = DB::Open(options, DBPATH, &db);
if (!s.ok()) {
    printf("open db failed: %s\n", s.ToString().c_str());
    return -1;
}

errno_t err = fopen_s(&file, "target.jpg", "rb");
if (err != 0 || file == nullptr) {
    printf("open file failed\n");
    delete db;
    return -1;
}

fseek(file, 0, SEEK_END);
long long size = ftell(file);
rewind(file);

char* buffer = (char*)calloc(1, size);
if (buffer == NULL) {
    printf("mem error\n");
    fclose(file);
    delete db;
    return -1;
}
fread(buffer, size, 1, file);

Slice value_slice(buffer, size);
Slice key_slice(&key_char, sizeof(key_char));
s = db->Put(woptions, key_slice, value_slice);
if (!s.ok()) {
    printf("put failed: %s\n", s.ToString().c_str());
}

free(buffer);
fclose(file);
delete db;

LevelDB BLOB存储说明

LevelDB没有单独定义BLOB类型,因为它的key和value本身就原生支持任意长度的二进制字节流,不需要额外配置或特殊处理。默认单value最大支持2GB,只要你的二进制文件大小不超过该阈值就可以正常存储。你测试RocksDB和BerkeleyDB没有报错的原因是这两个数据库的参数校验、内存访问容错逻辑和LevelDB不同,掩盖了你代码的错误,并非LevelDB本身不支持大二进制存储。


内容的提问来源于stack exchange,提问作者Jeong Hwan Im

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 15:06:01