views:

95

answers:

1

I'm converting an array of integers into a char by iterating through the whole array, and then I'm adding the resulting string to ncurses's method new_item. For some reason I'm doing something wrong the way I reallocate memory, thus I get the the first column as:

-4 Choice 1                 0 Choice 1
 4 Choice 2                 1 Choice 1
 4 Choice 3  - Instead of - 2 Choice 1
 4 Choice 4                 3 Choice 1
 4 Exit                     4 Choice 1

-

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <menu.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define CTRLD     4

char *choices[] = {
                        "Choice 1",
                        "Choice 2",
                        "Choice 3",
                        "Choice 4",
                        "Exit",
                  };
int table[5]={0,1,2,3,4}; 
int main()
{    ITEM **my_items;
    int c;              
    MENU *my_menu;
    int n_choices, i;
    ITEM *cur_item;

    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);

    n_choices = ARRAY_SIZE(choices);
    my_items = (ITEM **)calloc(n_choices + 1, sizeof(ITEM *));

    char *convert = NULL;
    for(i = 0; i < n_choices; ++i){
        convert = (char *) malloc ( sizeof(char) * 4);
        sprintf(convert, "%i", table[i]); 
        my_items[i] = new_item(convert, choices[i]);
    }
    my_items[n_choices] = (ITEM *)NULL;

    my_menu = new_menu((ITEM **)my_items);
    mvprintw(LINES - 2, 0, "F1 to Exit");
    post_menu(my_menu);
    refresh();

    while((c = getch()) != KEY_F(1))
    {   switch(c)
        {   case KEY_DOWN:
                menu_driver(my_menu, REQ_DOWN_ITEM);
                break;
            case KEY_UP:
                menu_driver(my_menu, REQ_UP_ITEM);
                break;
        }
    }

    char *n = NULL, *d = NULL;

    unpost_menu(my_menu);
    free_menu(my_menu);
    for(i = 0; i < n_choices; ++i){
       n = (char *) item_name (my_items[i]);
       free (n);
       d = (char *) item_description (my_items[i]);
       free (d);
       free_item(my_items[i]);
    }

    free(my_items);
    endwin();
}

**Update: This has been fixed. See code above!

+1  A: 

You attempt to realloc the same memory block with the same size again and again, for which realloc just returns the same memory block. So you are overwriting the earlier values of convert, and storing the same char array in all items.

You should use malloc instead:

// right here
char *convert = NULL;
for(i = 0; i < n_choices; ++i){
    convert = (char *) malloc (sizeof(char) * 4);
    sprintf(convert, "%i", table[i]); 
    my_items[i] = new_item(convert, choices[i]);
}
Péter Török
I actually did, (see code above) but valgrind throws 16 bytes in 4 blocks are definitely lost in loss record 4 of 21at 0x4023D6E: malloc (vg_replace_malloc.c:207)
Mike
@Mike: you also have to clean up all the memory you allocate.
Jonathan Leffler
@Jonathan Leffler: Am I missing something that I need to clean up? I'm freeing convert
Mike
@Mike: you only free up the last of the values allocated to `convert`; you need to clean up each the values - the ones assigned via the `new_item()` function to `my_items[i]`. Exactly how you do that I'm not sure; I'm not familiar with this specific `new_item()`. But since you iterate around the loop a number of times, allocating each time, but only free once, you are bound to be leaking memory (or, possibly, double-freeing - but Valgrind is saying you're leaking, not double-freeing).
Jonathan Leffler
@Jonathan Leffler: Thanks, as you mentioned, I wasn't freeing each of the values.
Mike