Указатели, списки и пустоты - PullRequest
1 голос
/ 03 января 2012

Я пытаюсь написать простой список.У меня есть следующий код:

#include "stdio.h"
#include "stdlib.h"

typedef struct _anObject {
  void* data;
  struct _anObject* previous;
  struct _anObject* next;
} object_t;


typedef struct _aHead {
  object_t* first;
  object_t* current;
  object_t* next;
  object_t* last;
  int index;
  int size;
} head_t;

head_t* new_list(void)
{
    head_t* list = malloc(sizeof(head_t));
    list->first = NULL;
    list->current = NULL;
    list->last = NULL;
    list->index = -1;
    list->size = 0;
    return list;
 }

void add_object_to_list(head_t* list, object_t* object)
{
    if (list->size == 0)
    {
    object->next = NULL;
    object->previous = NULL;
    list->first = object;
    list->current = object;
    list->last = object;
    list->index = 0;
    list->size = 1;
    } 
    else if (list->size > 0)
    {
    object->previous = list->last;
    object->next = NULL;
    list->current->next = object;
    list->current = object;
    list->last = object;
    list->size +=1;
    list->index = list->size - 1;
    }       
}

object_t* createIntObject(int value)
{
    int* data = &value;
    object_t* object = malloc(sizeof(object_t));
    object->data = data;
    return object;
}

int main(int argc, char** argv)
{
    head_t* list = new_list();
    object_t* obj;
    obj = createIntObject(22);
    add_object_to_list(list, obj);
    obj = createIntObject(44);
    add_object_to_list(list, obj);

    fprintf(stderr, "size number: %i\n", list->size);
    fprintf(stderr, "First data value on the list: %i\n", *(int*) list->first->data);
    fprintf(stderr, "Last data value on the list: %i\n", *(int*) list->last->data);

    free(list);
    free(obj);
    return 0;
 }

Я скомпилировал без предупреждения или ошибки, но когда я запускаю код, я получаю следующий и нежелательный результат:

size number: 2
Current data value on the list: 0
Current data value on the list: 0

делать неправильно?Любая помощь будет оценена

Ответы [ 3 ]

5 голосов
/ 03 января 2012

Ошибка в createIntObject, где вы возвращаете указатель на параметр функции:

object_t* createIntObject(int value) { /* deobfuscated */
    object_t* object = malloc(sizeof(object_t));
    object->data = &value; // <--
    return object;
}

Доступ к указателям на локальные переменные (включая параметры функции) после возвращения функции приводит к неопределенному поведению. Вместо этого выделите место для целочисленного значения с помощью malloc и присвойте его object->data.

Это распространенная ошибка новичка. Для получения дополнительной информации обратитесь к справочному вопросу или тегу local-variable .

Несколько других примечаний: если вы используете printf и malloc, вы должны #include <stdio.h> и #include <stdlib.h>.

Убедитесь, что ваш компилятор настроен на распознавание этих ошибок по умолчанию. Например, если вы не абсолютно уверены в внутренностях компилятора и стандарте C, хорошей идеей будет компилировать ваши программы с помощью gcc -std=c99 -pedantic -Wall -Werror.

Кроме того, успешная программа возвращает 0 по соглашению и код ошибки в противном случае.

3 голосов
/ 03 января 2012

Если это какое-то утешение (я сомневаюсь, что это так), когда я компилирую ваш код на MacOS X 10.7.2 с GCC 4.2.1 (LLVM), я получаю:

size number: 2
First data value on the list: 22
Last data value on the list: 44

Все, что я сделал, это добавил <stdio.h> и <stdlib.h>, сделал функции статическими и объявил int main(void), поскольку аргументы не используются.

Так почему бы вам не увидеть это?

  • Подумайте, где хранится значение, когда вы берете его адрес в createIntObject().

Также, когда вы создаете объект, вы должны установить для ссылок значение NULL - убедитесь, что вы полностью инициализировали объект.

0 голосов
/ 03 января 2012

Этот код хорошо работает

object_t* createInt(int value)
{
    object_t* object = malloc(sizeof(object_t));
    object->data = malloc(sizeof(int));
    *(int*)object->data = value;
    object->next = NULL;
    object->previous = NULL;
    return object;
}
...