0

我正在尝试在一个简单的程序中使用 BDB,但遇到了段错误问题。

Program received signal SIGSEGV, Segmentation fault.
__bamc_put (dbc=0x60e7f0, key=0x0, data=0x60b240, flags=6337152, pgnop=0x0)
    at ../src/btree/bt_cursor.c:2077
2077    ../src/btree/bt_cursor.c: No such file or directory.

gdb 回溯:

#0  __bamc_put (dbc=0x60e7f0, key=0x0, data=0x60b240, flags=6337152, pgnop=0x0)
    at ../src/btree/bt_cursor.c:2077
#1  0x0000000000404152 in bzing_inv_add (hnd=0x60c010, hash=..., data=80)
    at /atlas/www/libbzing/src/bzing.c:189
#2  0x00000000004041fa in bzing_block_add (hnd=0x60c010, 
    data=0x7fffb0d7d000 "\001", max_len=1163428803, actual_len=0x7fffffffe458)
    at /atlas/www/libbzing/src/bzing.c:217
#3  0x00000000004044d4 in bzing_index_regen (hnd=0x60c010, 
    data=0x7fffb0d7d000 "\001", len=1163428803)
    at /atlas/www/libbzing/src/bzing.c:269
#4  0x000000000040301c in main (argc=1, argv=0x7fffffffe628)
    at /atlas/www/libbzing/test/bzing_test.c:75

使用 valgrind memcheck 运行时,段错误消失,程序正常完成,没有来自 valgrind 的任何警告。

请注意,根据 gdb,__bamc_put 如何传递一个 NULL 指针作为关键参数。这似乎是造成段错误的明显罪魁祸首。但事情是这样的,DB->put 的第二个参数实际上应该是事务或非事务插入的 NULL。

这是我的代码:

DBT bdb_key, bdb_data;

memset(&bdb_key, 0, sizeof(DBT));
memset(&bdb_data, 0, sizeof(DBT));
bdb_key.data = hash.d8;
bdb_key.size = 32;
bdb_data.data = (char *) &data;
bdb_data.size = 8;

result = hnd->bdb_inv->put(hnd->bdb_inv, NULL, &bdb_key, &bdb_data, 0);

来自:https ://github.com/justmoon/bzing/blob/master/src/bzing.c

这是出现在文档和我找到的所有示例中的签名。

DB->put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags);

请参阅http://docs.oracle.com/cd/E17076_02/html/api_reference/C/dbput.html

如果我尝试使用 gdb 指示的签名(省略 DB_TXN 参数),我只会收到编译器警告,因为编译器根据文档使用正确的签名。

所以我想也许我链接到了错误的库?但:

$ ldd build/test/bzing_test | grep libdb
    libdb-5.1.so => /usr/lib/x86_64-linux-gnu/libdb-5.1.so (0x00007f28dd7ec000)
$ dpkg -L libdb5.1-dev
/.
/usr
/usr/share
/usr/share/doc
/usr/include
/usr/include/db.h
/usr/include/db_185.h
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libdb-5.1.a
/usr/share/doc/libdb5.1-dev
/usr/lib/x86_64-linux-gnu/libdb.a
/usr/lib/x86_64-linux-gnu/libdb.so
$ dpkg -L libdb5.1
/.
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libdb5.1
/usr/share/doc/libdb5.1/build_signature_amd64.txt
/usr/share/doc/libdb5.1/copyright
/usr/share/doc/libdb5.1/changelog.Debian.gz
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/libdb5.1
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libdb-5.1.so

编译器肯定在使用/usr/include/db.h,头文件和库都是 Ubuntu 包中的原始文件。我首先在 Ubuntu 11.10 上遇到了这个问题,升级到 Ubuntu 12.04 后它仍然存在。

我正在使用 CMake 和这些标志进行编译:

cd /atlas/www/libbzing/build/src && /usr/bin/gcc  -DBZING_BUILD -Wall -fvisibility=hidden -std=c99 -pedantic -DDEBUG -g -I/atlas/www/libbzing/build/src/../bzing-0.1.0/include/bzing/..    -o CMakeFiles/bzing_s.dir/bzing.c.o   -c /atlas/www/libbzing/src/bzing.c
...
/usr/bin/ar cr ../bzing-0.1.0/lib/libbzing_s.a  CMakeFiles/bzing_s.dir/bzing.c.o CMakeFiles/bzing_s.dir/bzing_parser.c.o CMakeFiles/bzing_s.dir/util.c.o
/usr/bin/ranlib ../bzing-0.1.0/lib/libbzing_s.a
...
/usr/bin/gcc   -Wall -fvisibility=hidden -std=c99 -pedantic -DDEBUG -g    CMakeFiles/bzing_test.dir/bzing_test.c.o  -o bzing_test -rdynamic -L/atlas/www/libbzing/build/test/../bzing-0.1.0/lib ../bzing-0.1.0/lib/libbzing_s.a -llmc -lpthread -lrt -lcrypto -ltokyocabinet -ldb -Wl,-rpath,/atlas/www/libbzing/build/test/../bzing-0.1.0/lib

如果我运行相同的程序,但选择哈希表数据库类型,我会遇到与 __hamc_put 相同的问题:

Program received signal SIGSEGV, Segmentation fault.
__hamc_put (dbc=0x60e7f0, key=0x0, data=0x60b240, flags=6337152, pgnop=0x0)
    at ../src/hash/hash.c:1068

我试过-fPIC了,但得到了相同的结果。

任何帮助将不胜感激。也许我走错了路,而 gdb 只是出于某种原因显示了错误的签名,但问题出在其他地方?

更新:

看起来 ->put 指针是错误的。它应该指向 __db_put_pp:

dbp->put = __db_put_pp;

(db_method.c 第 248 行)

但指向__bamc_put/__hamc_put代替:

Breakpoint 3, bzing_inv_add (hnd=0x60c010, hash=..., data=80)
    at /atlas/www/libbzing/src/bzing.c:189
189     result = hnd->bdb_inv->put(hnd->bdb_inv, NULL, &bdb_key, &bdb_data, 0);
(gdb) print hnd->bdb_inv->put
$1 = (int (*)(DB *, DB_TXN *, DBT *, DBT *, 
    u_int32_t)) 0x7ffff7034d00 <__hamc_put>
4

1 回答 1

1

“缺失”参数是因为当您到达__bamc_put(或__hamc_put)时,事务已移至dbc参数中。(这是一个“数据库游标”。)我不太明白为什么上面没有框架__bamc_put,因为它是通过另一层调用的(实际上是两个:__db_put_pp然后__db_put)。

尤其奇怪的是它会与 valgrind 一起工作,而没有它就会失败。

于 2012-05-01T05:31:06.410 回答