1

我有一个程序可以使用 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 时,它会突然起作用吗?

4

1 回答 1

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;
于 2013-06-30T22:28:43.193 回答