1

I'm trying to write a simple list. I have the next code:

#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;
 }

I compiled without any warning or error, but when I run the code I obtain the next and not wanted result:

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

What am i doing wrong? Any help will be appreciated

xbelanch
  • 844
  • 1
  • 12
  • 21

3 Answers3

5

The error is in createIntObject, where you return a pointer to a function parameter:

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

Accessing pointers to local variables (including the function parameters) once the function has returned yields undefined behavior. Instead, allocate space for the integer value with malloc, and assign that to object->data.

This is a common beginner mistake. For more information, refer to the reference question or the local-variables tag.

A couple of other notes: If you use printf and malloc, you must #include <stdio.h> and #include <stdlib.h>.

Make sure your compiler is set to recognize these errors by default. For example, unless you are absolutely certain of compiler internals and the C standard, it's a good idea to compile your programs with gcc -std=c99 -pedantic -Wall -Werror.

Also, a successful program returns 0 by convention, and an error code otherwise.

Community
  • 1
  • 1
phihag
  • 278,196
  • 72
  • 453
  • 469
3

If it is any consolation (I doubt if it is), when I compile your code on MacOS X 10.7.2 with GCC 4.2.1 (LLVM), I get:

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

All I did was add <stdio.h> and <stdlib.h>, make the functions static, and declare int main(void) since the arguments are unused.

So, why might you not be seeing this?

  • Think about where the value is stored when you take the address of it in createIntObject().

Also, when you create the object, you should set the links to NULL - make sure you completely initialize the object.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

This code works well

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;
}
xbelanch
  • 844
  • 1
  • 12
  • 21