1
typedef struct _DocumentRow
{
    char * code /** The code */;
    char * designation /** The designation */;
    double quantity /** The quantity */;
    char * unity /** The unity */;
    double basePrice /** The base price */;
    double sellingPrice /** The selling price */;
    double discount /** The discount */;
    double rateOfVAT /** The rate of VAT */;
    struct _DocumentRow * next /** The pointer to the next row */;
} DocumentRow;

void DocumentRowList_init(DocumentRow ** list) {
    DocumentRow *L;
    list = ( DocumentRow ** ) malloc( sizeof( DocumentRow* ) );
    if ( list == NULL ) {
        fatalError( "memory is not enough" );
    }
    L = NULL;
    list = &L;
}

After using the function DocumentRowList_init, when I test if ( *list == NULL ), it evaluates to false, why ? I have already set list = &L and L = NULL.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Alex
  • 11
  • 1
  • don't follow you question... if *list==NULL returns 0, *list is not NULL. – tristan Jan 03 '14 at 08:06
  • 1
    `list` is local. `*list = L;` to set. – BLUEPIXY Jan 03 '14 at 08:06
  • 1
    To me, this code seems to do nothing, e.g. `L = NULL; list = &L;`?! – Sebastian Jan 03 '14 at 08:07
  • also `L = malloc( sizeof( DocumentRow ) );` `if(L == NULL) ...` – BLUEPIXY Jan 03 '14 at 08:08
  • 1
    What you wrote is called a memory leak. You allocate memory pointed by `list` and then you make `list` to point somewhere else. You will not be able to `free(list)`. And `*list` is not `NULL` because `*list` is `L` which is a pointer to `NULL`. Outside this function, testing `*list` may result in a segmentation fault. – francis Jan 03 '14 at 08:12
  • set to NULL `void DocumentRowList_init(DocumentRow ** list) { *list = NULL; }`, – BLUEPIXY Jan 03 '14 at 08:12
  • some other minor points in your code: (1) identifiers starting with `_` and a capital letter are reserved, you shouldn't use them. Here it is compiletely sufficient to use the same identifier as `struct` tag as for the `typedef`. (2) don't cast the return of `malloc`: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Jens Gustedt Jan 03 '14 at 08:16

3 Answers3

2

Looks like you want to change (initialize) something pointed to by list, here is how it usually be done:

void DocumentRowList_init(DocumentRow ** list) {
    *list = ( DocumentRow * ) malloc( sizeof( DocumentRow ) );
    if ( *list == NULL ) {
        fatalError( "memory is not enough" );
    }
}
Lee Duhem
  • 14,695
  • 3
  • 29
  • 47
  • You malloc only `size(DocumentRow*)` bytes for a pointer, not `size(DocumentRow)` for the struct. In this case the type cast to `( DocumentRow ** )` is correct. – Boris Brodski Jan 03 '14 at 08:30
2

You would have undefined behaviour here. L is a local variable, so when you return it's address via the pointer pointer, the variable no longer exists when DocumentRowList_init is returning.

So even though you assign NULL to it, it will point to invalid memory.

But list is local to DocumentRowList_init, so it will not return the value anyway, as you only assign it a value and then return.

If you want to return a structure of DocumentRow you'd have to use this

  *list = malloc( sizeof *L);

to allocate a structure and return the pointer to it.

Devolus
  • 21,661
  • 13
  • 66
  • 113
0
void DocumentRowList_init(DocumentRow ** list) {
    DocumentRow *L;
    list = ( DocumentRow ** ) malloc( sizeof( DocumentRow* ) );
    if ( list == NULL ) {
        fatalError( "memory is not enough" );
    }
    L = NULL;
    list = &L;
}

Please mind that list=&L assigns list the address of a variable located on the stack. So once you exist the function the variable is out of scope and your list is left pointing to a some location (on the stack).

Pandrei
  • 4,843
  • 3
  • 27
  • 44
  • So, what can I do ? I want to make *list = NULL, but it also can't work – Alex Jan 03 '14 at 12:09
  • you can make DocumentRow *L a global variable; or dynamically allocate memory for L: L= (DocumentRow *)malloc(sizeof(DocumentRow *)) – Pandrei Jan 03 '14 at 12:15