C 中的 Malloc 问题

发布于 2024-10-20 00:49:50 字数 1760 浏览 2 评论 0原文

解决方案:分配的内存在程序退出后被释放。必须从磁盘读+写回链表,然后重写以更新数据库!谢谢大家 =)

你好,过去几个晚上我基本上一直在研究这个数据库程序,但我只是不断进入死胡同。作业今天到期,所以如果您能帮助我,我将不胜感激。 =T

数据库是用链表实现的,由几个文件组成:sdbm.c、sdbm.h、new.c、get.c、insert.c、put.c 和remove.c。 sdbm.c 保存基于 sdbm.h 接口的数据库方法,其他文件包含使用 sdbm 方法的主要方法。

第一个问题与插入程序有关,当我尝试添加键和值对时,它似乎工作正常......也就是说,直到我们再次尝试调用插入程序。分配的内存好像消失了!我一直在研究,试图找出为什么即使我已经分配了内存,为什么它在插入程序退出后会消失。这里是一些代码:

  • 节点结构+全局变量:
struct dbase_Node {
  char *keyValue;
  char *element;
  struct dbase_Node *next;
};

typedef struct dbase_Node Node;

Node *head;

========

  • 插入方法
static bool sdbm_insert_back(Node **headRef, const char *key, const char *value)
{
  Node *new = (Node *)malloc(sizeof(Node));
  if (new == NULL)
    return false;
  else {
    new->keyValue = malloc(strlen(key));
    new->element = malloc(strlen(value));
    strcpy(new->keyValue, key);
    strcpy(new->element, value);

    new->next = *headRef;
    *headRef = new;
    return true;
  }
}
  • 同步方法
bool sdbm_sync()
{
  if (!isOpen()) { return false; }

  if (fopen(databaseName, "w" ) == NULL) {
    error = SDBM_FOPEN_FAILED;
    return false;
  }

  Node *current = head;

  while (current != NULL) {
    fprintf(database, "Key: %s\n", current->keyValue);
    fprintf(database, "Value: %s\n", current->element);
    current = current->next;
  }
  return true;
}

我运行以下

: ./new [database] <-- 工作正常 ./insert [database] [key] [value] <--似乎工作正常

然后在我尝试插入更多之后,已经添加的节点消失了......

Solution: Allocated memory is freed up after a program exits. Have to read+write from disk back into a linked list, and then rewrite to update the database! Thank you everyone =)

Hello, I've basically been working on this database program for the past few nights but I just continuously reach dead ends. The assignment is due today so if you could help me out, it would be very much appreciated. =T

The database is implemented with a Linked List and consists of a few files: sdbm.c, sdbm.h, new.c, get.c, insert.c, put.c, and remove.c. sdbm.c holds the methods for the database based on the sdbm.h interface, and the other files contain main methods that use the methods from sdbm.

The first problem comes with the insert program, which seems to work fine when I try to add in a key and value pair ... that is, until we try to call the insert program again. The memory allocated seems to have disappeared! I've been researching, trying to figure out why even though I have malloced, why does it disappear after the insert program exits. Here is some code:

  • The node structure + global variable:
struct dbase_Node {
  char *keyValue;
  char *element;
  struct dbase_Node *next;
};

typedef struct dbase_Node Node;

Node *head;

========

  • The insert method
static bool sdbm_insert_back(Node **headRef, const char *key, const char *value)
{
  Node *new = (Node *)malloc(sizeof(Node));
  if (new == NULL)
    return false;
  else {
    new->keyValue = malloc(strlen(key));
    new->element = malloc(strlen(value));
    strcpy(new->keyValue, key);
    strcpy(new->element, value);

    new->next = *headRef;
    *headRef = new;
    return true;
  }
}
  • The sync method
bool sdbm_sync()
{
  if (!isOpen()) { return false; }

  if (fopen(databaseName, "w" ) == NULL) {
    error = SDBM_FOPEN_FAILED;
    return false;
  }

  Node *current = head;

  while (current != NULL) {
    fprintf(database, "Key: %s\n", current->keyValue);
    fprintf(database, "Value: %s\n", current->element);
    current = current->next;
  }
  return true;
}

I run the following:

./new [database] <-- works fine
./insert [database] [key] [value] <--seems to work fine

And then after I try to insert more, the already added nodes have disappeared ...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

云胡 2024-10-27 00:49:50
new->keyValue = malloc(strlen(key));
new->element = malloc(strlen(value));
strcpy(new->keyValue, key);
strcpy(new->element, value);

这会导致差一缓冲区溢出。
您需要为终止 \0 分配空间,因此请使用 strlen(key) + 1strlen(value) + 1

或者甚至更好,使用strdup():

new->keyValue = strdup(key);
new->element = strdup(value);

程序存在后数据丢失的问题非常简单,但修复起来并不容易:除了内存中之外,您没有将其存储在任何地方。当程序退出时,内存会自动释放。
因此,您必须将其存储在文件中。

new->keyValue = malloc(strlen(key));
new->element = malloc(strlen(value));
strcpy(new->keyValue, key);
strcpy(new->element, value);

This causes an off-by-one buffer overflow.
You need to allocate space for the terminating \0, so use strlen(key) + 1 and strlen(value) + 1.

Or even better, use strdup():

new->keyValue = strdup(key);
new->element = strdup(value);

The problem of your data being lost after the program exists is very simple but not simple to fix: You are not storing it anywhere but in memory. And memory is automatically free'd when the program exits.
So you'll have to store it e.g. in a file.

霓裳挽歌倾城醉 2024-10-27 00:49:50

你的问题中的这一行:

./new [database] <-- 工作正常 ./insert [database] [key] [value] <-- 似乎工作正常

意味着您运行程序一次来创建数据库,然后再次创建密钥/值对。您是否在任何地方将数据保存到磁盘?

This line in your question:

./new [database] <-- works fine ./insert [database] [key] [value] <--seems to work fine

implies you are running the program once to create a database, then again to create the key/value pairs. Are you anywhere persisting your data to disk?

森末i 2024-10-27 00:49:50

我读得对吗?对于每一项操作,您都要启动一个新流程吗?如果是这样,那就有问题了:一旦进程终止,它分配的所有内存都会被释放。

您需要的是持久存储。在通常的操作系统中,进程内存不是持久的(有一些操作系统,分配的内存是持久的,但仍然绑定到某个进程,所以即使在这样的操作系统中,这种程序也无法工作)。

Do I read that right? For each of those operations you're starting a new process? If so there's your problem: Once a process terminates all the memory it allocated is freed.

What you need is persistent storage. In the usual operating systems process memory is not persistent (there are some OS in which allocated memory is persistent, but still bound to a certain process, so even in such a OS this kind of program won't work).

你对谁都笑 2024-10-27 00:49:50

我觉得问题出在 else 部分,你需要检查它是否是列表中的第一个节点,如果是的话分配内存,存储到 head 中。下次你调用它时,如果列表不为空,则链接 head->next 到你新创建的列表。

I feel the issue is in the else part, u need to check if it's the first node in the List if so allocate memory, store into head. Next time u call it if the list is not null then link head->next to ur newly created one.

So要识趣 2024-10-27 00:49:50

建议:在sdbm_sync中写入数据后关闭文件。

另外,在sdbm_sync中,database定义在哪里? fopen 行是否缺少某些内容? ???

bool sdbm_sync()
{
  if (!isOpen()) { return false; }
  /* ******** MISSING DATABASE ? ? ? ? ?
  FILE *database;
  if ((database = fopen(databaseName, "w" )) == NULL) {
  ******** */
  if (fopen(databaseName, "w" ) == NULL) {
    error = SDBM_FOPEN_FAILED;
    return false;
  }

  Node *current = head;
  while (current != NULL) {
    fprintf(database, "Key: %s\n", current->keyValue);
    fprintf(database, "Value: %s\n", current->element);
    current = current->next;
  }
  if (!fclose(database)) /* unexpected error closing database */;
  return true;
}

Suggestion: in sdbm_sync close the file after writing the data.

Also in sdbm_sync where is database defined? Is the fopen line missing somthing? ???

bool sdbm_sync()
{
  if (!isOpen()) { return false; }
  /* ******** MISSING DATABASE ? ? ? ? ?
  FILE *database;
  if ((database = fopen(databaseName, "w" )) == NULL) {
  ******** */
  if (fopen(databaseName, "w" ) == NULL) {
    error = SDBM_FOPEN_FAILED;
    return false;
  }

  Node *current = head;
  while (current != NULL) {
    fprintf(database, "Key: %s\n", current->keyValue);
    fprintf(database, "Value: %s\n", current->element);
    current = current->next;
  }
  if (!fclose(database)) /* unexpected error closing database */;
  return true;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文