Проблема Маллока в Си - PullRequest
0 голосов
/ 04 марта 2011

Решение: выделенная память освобождается после выхода из программы.Приходится читать + записывать с диска обратно в связанный список, а затем переписывать для обновления базы данных!Всем спасибо =)

Здравствуйте, я в основном работал над этой программой базы данных последние несколько ночей, но я просто постоянно захожу в тупик.Назначение назначено сегодня , поэтому, если бы вы могли мне помочь, это было бы очень признательно.= T

База данных реализована с помощью связанного списка и состоит из нескольких файлов: sdbm.c, sdbm.h, new.c, get.c, insert.c, put.c и remove.с.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 [база данных] <- работает нормально ./insert [база данных] [ключ] [значение] <- кажется, работает нормально </p>

А потом, после того, как я пытаюсь вставить больше, уже добавленные узлы исчезли ...

Ответы [ 5 ]

5 голосов
/ 04 марта 2011
new->keyValue = malloc(strlen(key));
new->element = malloc(strlen(value));
strcpy(new->keyValue, key);
strcpy(new->element, value);

Это приводит к переполнению буфера.Вам нужно выделить место для окончания \0, поэтому используйте strlen(key) + 1 и strlen(value) + 1.

Или, что еще лучше, используйте strdup():

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

.Проблема потери ваших данных после того, как программа существует, очень проста, но ее не просто решить: вы храните ее не где-нибудь, а в памяти.И память автоматически освобождается при выходе из программы.Поэтому вам придется хранить его, например, в файле.

1 голос
/ 04 марта 2011

Я правильно понял? Для каждой из этих операций вы начинаете новый процесс? Если это так, то есть ваша проблема: после завершения процесса вся память, выделенная ему, освобождается.

Вам нужно постоянное хранилище. В обычных операционных системах память процесса не является постоянной (есть некоторые ОС, в которых выделенная память является постоянной, но все еще связана с определенным процессом, поэтому даже в такой ОС такая программа не будет работать).

1 голос
/ 04 марта 2011

Эта строка в вашем вопросе:

. / New [база данных] <- работает нормально ./insert [база данных] [ключ] [значение] <- кажется, работает нормально </p>

подразумевает, что вы запускаете программу один раз для создания базы данных, а затем снова для создания пар ключ / значение. Сохраняете ли вы где-нибудь свои данные на диск?

0 голосов
/ 04 марта 2011

Предложение: в 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;
}
0 голосов
/ 04 марта 2011

Я чувствую, что проблема в остальной части, вам нужно проверить, если это первый узел в списке, если так распределить память, сохранить в голове.В следующий раз, когда вы вызовете его, если список не равен нулю, тогда ссылка head-> рядом с вашим недавно созданным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...