我有一个程序可以使用 GDBM 或京都内阁作为 DBM 库。我编写了一些函数来抽象出两者之间的差异,并且我传递了 void 指针来代替数据库文件(GDBM_FILE
在 GDBM 和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()
,它是我正在使用的唯一 void 指针(在这个测试程序中,foo
指针应该只是一个健全性检查)。
我确信在 C 语言中内存分配的变幻莫测中有一些我忘记或不理解的东西。当引用 int 的 void 指针没有时,为什么引用 GDBM 数据库的 void 指针会丢失/损坏?为什么,当我不尝试将取消引用的 void 指针存储foo
到 int 时,它会突然起作用吗?