0

I should dynamically allocate an array of pointers to structure, passing from time to time parameters for a single structure. sorry if I can not explain, here is the code

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>


typedef struct _DROP_DOWN_MENU_LABELS
{
    char *title;
    char **items;
} MenuLabels;

MenuLabels ** ml_init(void)
{
    MenuLabels **ml;
    ml=(MenuLabels **)calloc(2,sizeof(MenuLabels*));
    ml[1]=NULL;
    return ml;
}



void addit(MenuLabels **mlabels, char *title, char *elems,...)
{

    int j;
    for (j=0; mlabels[j]!=NULL ; j++ );
    printf("\n\nCHECK:MenuLabels has %d menu",j);

    mlabels=(MenuLabels **)realloc(mlabels,(j+2)*sizeof(MenuLabels*));

    mlabels[j]=(MenuLabels *)malloc(1*sizeof(MenuLabels));

    mlabels[j+1]=NULL;




    mlabels[j]->title=title;

    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    int i=0;
    char **mitems=NULL;
    mitems=(char **)malloc(sizeof(char*));
    mitems[i]=elems;

    va_list argP;
    va_start(argP, elems);

    char *p;
    for (i=1; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
    {
        mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
        mitems[i]=p;
    }

    if (!p)
    {
        mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
        mitems[i]=NULL;
    }

    va_end(argP);
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

    mlabels[j]->items=mitems;
}



int main()
{
    MenuLabels **ml;
    ml=ml_init();
    addit(ml,"FILE","new","open","save","backup","print","setup","exit",NULL);
    addit(ml,"AFILE","Anew","Asave","Abackup","Aexit",NULL);
    addit(ml,"BFILE","Bnew","Bopen","Bsave","Bprint","Bexit",NULL);

    free(ml);

    fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
    return 0;
}

starting the program seems to be executed without errors:

CHECK:MenuLabels has 0 menu

CHECK:MenuLabels has 1 menu

CHECK:MenuLabels has 2 menu
***END***

Process returned 0 (0x0)   execution time : 0.001 s
Press ENTER to continue.

but checking with valgrind:

==5572== Memcheck, a memory error detector
==5572== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5572== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5572== Command: ./prove
==5572== 


==5572== Invalid read of size 8
==5572==    at 0x400812: addit (main.c:26)
==5572==    by 0x400B27: main (main.c:75)
==5572==  Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==5572==    at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572==    by 0x400855: addit (main.c:29)
==5572==    by 0x400AF1: main (main.c:74)
==5572==  Block was alloc'd at
==5572==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572==    by 0x40075C: ml_init (main.c:15)
==5572==    by 0x400AB0: main (main.c:73)
==5572== 
CHECK:MenuLabels has 0 menu

==5572== Invalid free() / delete / delete[] / realloc()
==5572==    at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572==    by 0x400855: addit (main.c:29)
==5572==    by 0x400B27: main (main.c:75)
==5572==  Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==5572==    at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572==    by 0x400855: addit (main.c:29)
==5572==    by 0x400AF1: main (main.c:74)
==5572==  Block was alloc'd at
==5572==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572==    by 0x40075C: ml_init (main.c:15)
==5572==    by 0x400AB0: main (main.c:73)
==5572== 
==5572== Invalid write of size 8
==5572==    at 0x400882: addit (main.c:31)
==5572==    by 0x400B27: main (main.c:75)
==5572==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5572== 
==5572== 
==5572== Process terminating with default action of signal 11 (SIGSEGV)
==5572==  Access not within mapped region at address 0x0
==5572==    at 0x400882: addit (main.c:31)
==5572==    by 0x400B27: main (main.c:75)
==5572==  If you believe this happened as a result of a stack
==5572==  overflow in your program's main thread (unlikely but
==5572==  possible), you can try to increase the size of the
==5572==  main thread stack using the --main-stacksize= flag.
==5572==  The main thread stack size used in this run was 8388608.
CHECK:MenuLabels has 0 menu==5572== 
==5572== HEAP SUMMARY:
==5572==     in use at exit: 112 bytes in 4 blocks
==5572==   total heap usage: 14 allocs, 10 frees, 1,392 bytes allocated
==5572== 
==5572== 16 bytes in 1 blocks are definitely lost in loss record 2 of 4
==5572==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572==    by 0x400881: addit (main.c:31)
==5572==    by 0x400B27: main (main.c:75)
==5572== 
==5572== 96 (16 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
==5572==    at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572==    by 0x400855: addit (main.c:29)
==5572==    by 0x400AF1: main (main.c:74)
==5572== 
==5572== LEAK SUMMARY:
==5572==    definitely lost: 32 bytes in 2 blocks
==5572==    indirectly lost: 80 bytes in 2 blocks
==5572==      possibly lost: 0 bytes in 0 blocks
==5572==    still reachable: 0 bytes in 0 blocks
==5572==         suppressed: 0 bytes in 0 blocks
==5572== 
==5572== For counts of detected and suppressed errors, rerun with: -v
==5572== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
./run_valgrind: riga 4:  5572 Errore di segmentazione (core dump creato) valgrind --leak-check=full --track-origins=yes --tool=memcheck ./prove

and in fact if I try to extract any value from ml at the end (eg ml[n]-> title) it goes into segmentation fault

what am I doing wrong? thank you all in advance

2
  • 1
    Unrelated to your problem, but symbols beginning with a leading underscore followed by an upper-case letter (like _DROP_DOWN_MENU_LABELS in your code) are reserved for the compiler and standard library in all scopes. Commented Apr 6, 2018 at 15:18
  • 1
    Your error trace refers to line 29, in the middle of the code you've left out. Try looking there. Alternately, provide an MVCE Commented Apr 6, 2018 at 18:03

2 Answers 2

2

Here's one problem:

char **mitems;
// ... assuming there's a mitems = malloc(...) or similar here...
mlabels[j]->items=mitems;
free(mitems);

Here you have a a pointer, you make it point to some memory you allocate, you copy the pointer (so you have two pointers pointing to the same memory) and then you free the memory that both pointers are pointing to.

The free call makes not only mitems invalid, but also mlabels[j]->items.

Sign up to request clarification or add additional context in comments.

1 Comment

ok thanks, mitems is rightly allocated, even if I remove free (mitems); the problem remains
0

I solved ... here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>


typedef struct s_drop_down_menu_labels
{
    char *title;
    char **items;
} MenuLabels;

MenuLabels ** ml_init(void)
{
    MenuLabels **ml;
    ml=(MenuLabels **)calloc(2,sizeof(MenuLabels*));
    ml[1]=NULL;
    return ml;
}



void addit(MenuLabels ***mlabels, char *title, char *elems,...)
{
    int j;
    for (j=0; (*mlabels)[j]!=NULL ; j++ );
    printf("\n\nCHECK:MenuLabels has %d menu",j);

    *mlabels=(MenuLabels **)realloc(*mlabels,(j+2)*sizeof(MenuLabels*));
    (*mlabels)[j]=(MenuLabels *)malloc(1*sizeof(MenuLabels));
    (*mlabels)[j+1]=NULL;

    (*mlabels)[j]->title=title;

    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
    int i=0;
    char **mitems=NULL;
    mitems=(char **)malloc(sizeof(char*));
    mitems[i]=elems;

    va_list argP;
    va_start(argP, elems);

    char *p;
    for (i=1; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
    {
        mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
        mitems[i]=p;
    }

    if (!p)
    {
        mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
        mitems[i]=NULL;
    }

    va_end(argP);
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

    (*mlabels)[j]->items=mitems;
    free(mitems);
}


int main()
{
    MenuLabels **ml;
    ml=ml_init();
    addit(&ml,"FILE","new","open","save","backup","print","setup","exit",NULL);
    addit(&ml,"AFILE","Anew","Asave","Abackup","Aexit",NULL);
    addit(&ml,"BFILE","Bnew","Bopen","Bsave","Bprint","Bexit",NULL);
    addit(&ml,"CFILE","Cnew","Copen","Csave","Cbackup","Cprint","Csetup","Cexit",NULL);
    addit(&ml,"DFILE","Dnew","Dsave","Dbackup","Dexit",NULL);
    addit(&ml,"EFILE","Enew","Eopen","Esave","Eprint","Eexit",NULL);


    printf("\n**********CHECK: %s",ml[3]->title);

for (int i=0;ml[i]!=NULL ;i++ )
    free(ml[i]);

    fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
    return 0;
}

@Some_programmer_dude, if not free mitems then there will be no more accessible memory allocated ...thank you all

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.