我有一个程序可以使用GDBM或Kyoto Cabinet作为DBM库。我已经编写了一些函数来抽象出两者之间的区别,并且我传递了无效指针来代替数据库文件(在GDBM的情况下为GDBM_FILE
,在京都内阁的情况下为KCDB *
) 。使用KC的一切工作正常,但是当我尝试使用GDBM后端时,数据库会以某种方式“丢失”传递给不同的函数。当我尝试转换指针并取消引用它,然后将其传递给其中一个GDBM函数时,会出现段错误并在调试器中抱怨db文件不存在。
以下是一些可以重现问题的代码:
#include <gdbm.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
void *
dbopen (void)
{
printf ("opening\n");
GDBM_FILE database = gdbm_open ("test.db", 512, GDBM_WRCREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, NULL);
if (!database)
{
printf ("cannot open database\n");
return NULL;
}
void *db = &database;
return db;
}
void
dbclose (void *db, void *foo)
{
printf ("%d\n", *(int *)foo);
GDBM_FILE database = *(GDBM_FILE *)db;
if (!database)
{
printf ("database lost\n");
return;
}
printf ("closing\n");
gdbm_close (database);
return;
}
void
fun (void *db, void *foo)
{
GDBM_FILE database = *(GDBM_FILE *)db;
datum key, value;
int bar = *(int *)foo; /* and yet, if I remove this line and the next */
printf ("%d\n", bar); /* one, it works! */
printf ("%d\n", *(int *)foo);
if (!database)
printf ("no db?\n");
key.dptr = "baz";
key.dsize = 4;
value.dptr = "quux";
value.dsize = 4;
printf ("storing\n");
gdbm_store (database, key, value, GDBM_REPLACE);
printf ("all done\n");
return;
}
int
main (void)
{
int foo = 5;
void *dbp = dbopen ();
void *foop = &foo;
fun (dbp, foop);
dbclose (dbp, foop);
}
当我运行该代码时,它会在调用gdbm_close()
时出现“找不到文件”错误。正如注释所示,如果我没有将其他void指针显式存储到int,那么程序运行就好了。
在我的实际程序中,当我调用gdbm_store()
时,它会“丢失”,并且它是我正在使用的唯一无效指针(在此测试程序中,foo
指针应该是理智检查。)
我确信C中的内存分配变幻莫测,我忘了或不理解。当引用int的void指针不引用时,为什么引用GDBM数据库的void指针会丢失/损坏?为什么,当我不尝试将解除引用的void指针foo
存储到int时,它是否突然起作用?
答案 0 :(得分:0)
您的问题是获取从gdbm_open
返回的指针的地址,而不是它的值。令人困惑的部分来自GDBM_FILE
的定义 - 它是指向结构的指针:
typedef struct {int dummy[10];} *GDBM_FILE;
你得到它的地址,即指针的位置,而不是指针值:
void *db = &database;
可以通过以下方式替换转换行来解决问题:
void *db = (void *)database;
和
GDBM_FILE database = (GDBM_FILE)db;