View Full Version : [C] problema allocazione puntatore a puntatore
marilynm69
04-04-2018, 13:45
Ciao a tutti, ho un problema con una funzione che deve prendere in ingresso un numero variable di stringhe e creare un puntatore ad array di puntatore a char (le stringhe caricate).
codice:
void addit( char *title, char *elems,...)
{
va_list argP;
va_start(argP, elems);
char **mitems;
mitems=(char **)xMalloc(sizeof(char*));
char *p;
int i;
for (i=0; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=xRealloc(mitems,sizeof(mitems)+sizeof(*mitems));
mitems[i]=(char *)xCalloc(1, sizeof(char*));
mitems[i]=p;
printf("\n\t%d: %s",i+1, p);
printf("\n\t\t+++ %s",mitems[i]);
}
printf("\n\n%d arguments\n", i);
va_end(argP);
}
int main()
{
addit("FILE","new","open","save","backup","print","setup","exit",NULL);
return 0;
}
valgrind:
==13035== Memcheck, a memory error detector
==13035== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==13035== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==13035== Command: ./serate\ project
==13035==
1: open
+++ open
2: save
==13035== Invalid write of size 8
==13035== at 0x4077CD: addit (Menu.c:440)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035== Address 0x6dbd620 is 0 bytes after a block of size 16 alloc'd
==13035== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13035== by 0x406B60: xRealloc (Menu.c:32)
==13035== by 0x40779B: addit (Menu.c:439)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035==
==13035== Invalid write of size 8
==13035== at 0x4077F1: addit (Menu.c:441)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035== Address 0x6dbd620 is 0 bytes after a block of size 16 alloc'd
==13035== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13035== by 0x406B60: xRealloc (Menu.c:32)
==13035== by 0x40779B: addit (Menu.c:439)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035==
+++ save
==13035== Invalid read of size 8
==13035== at 0x407832: addit (Menu.c:444)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035== Address 0x6dbd620 is 0 bytes after a block of size 16 alloc'd
==13035== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13035== by 0x406B60: xRealloc (Menu.c:32)
==13035== by 0x40779B: addit (Menu.c:439)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035==
3: backup
+++ backup
4: print
+++ print
5: setup
+++ setup
6: exit
+++ exit
6 arguments
==13035==
==13035== HEAP SUMMARY:
==13035== in use at exit: 64 bytes in 7 blocks
==13035== total heap usage: 14 allocs, 7 frees, 1,176 bytes allocated
==13035==
==13035== 16 bytes in 1 blocks are definitely lost in loss record 1 of 2
==13035== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13035== by 0x406B60: xRealloc (Menu.c:32)
==13035== by 0x40779B: addit (Menu.c:439)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035==
==13035== 48 bytes in 6 blocks are definitely lost in loss record 2 of 2
==13035== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13035== by 0x406B14: xCalloc (Menu.c:22)
==13035== by 0x4077CC: addit (Menu.c:440)
==13035== by 0x40791C: temp (Menu.c:456)
==13035== by 0x406A93: main (main.c:32)
==13035==
==13035== LEAK SUMMARY:
==13035== definitely lost: 64 bytes in 7 blocks
==13035== indirectly lost: 0 bytes in 0 blocks
==13035== possibly lost: 0 bytes in 0 blocks
==13035== still reachable: 0 bytes in 0 blocks
==13035== suppressed: 0 bytes in 0 blocks
==13035==
==13035== For counts of detected and suppressed errors, rerun with: -v
==13035== ERROR SUMMARY: 14 errors from 5 contexts (suppressed: 0 from 0)
a me servirebbe una cosa così:
https://s14.postimg.org/qlhg7w8tt/x_forum.jpg
il problema più grosso è ovviamente quello della memoria, poi non capisco perchè inizia a prendermi il secondo dei parametri variabili("open"), invece che dal prino ("new").
grazie anticipatamente...
P.S. le funzioni xMalloc, xCalloc, xRealloc sono remplicemente malloc, calloc e realloc con il controllo sulla memoria allocata, e restituiscono il puntatore o chiudono il programma
grigor91
04-04-2018, 17:17
Ciao a tutti, ho un problema con una funzione che deve prendere in ingresso un numero variable di stringhe e creare un puntatore ad array di puntatore a char (le stringhe caricate).
codice:
void addit( char *title, char *elems,...)
{
va_list argP;
va_start(argP, elems);
...
}
int main()
{
addit("FILE","new","open","save","backup","print","setup","exit",NULL);
return 0;
}
il problema più grosso è ovviamente quello della memoria, poi non capisco perchè inizia a prendermi il secondo dei parametri variabili("open"), invece che dal prino ("new").
grazie anticipatamente...
P.S. le funzioni xMalloc, xCalloc, xRealloc sono remplicemente malloc, calloc e realloc con il controllo sulla memoria allocata, e restituiscono il puntatore o chiudono il programma
title punta al primo carattere di "FILE", elems al primo carattere di "new", quindi il primo argomento variabile è "open".
Inoltre quando effettui la reallocazione la nuova dimensione è formata dalla somma della dimensione dei due puntatori, che quindi sarà sempre costante (8 o 16 byte in base all'architettura).
se non ho capito male
main (int argc, char *argv[] )
{
}
e fa già quello che chiedi
marilynm69
04-04-2018, 18:21
in va_start(argP, elems);
elemsnon deve essere l'ultimo degli argomenti fissi? quindi new,...
char * title è un'altra cosa a parte da quella lista...inizia da open anche se sostituisco char *title con int title e ci passo un numero, come potrebbe pure tranquillamente essere...
per riallocare non ho capito come allora dovrei fare...
marilynm69
04-04-2018, 18:23
se non ho capito male
main (int argc, char *argv[] )
{
}
e fa già quello che chiedi
non mi serve,nell'esempio c'è main ma la funzione è interna ad un altra, a sua volta interna al main...
marilynm69
04-04-2018, 19:17
per l'allocazione ho risolto, grazie grigor91 per avermi fatto notare...
ho fatto così:
…..
char **mitems;
mitems=(char **)xMalloc(sizeof(char*));
int i;
for (i=0; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=(char **)xRealloc(mitems,(i+1)*sizeof(char*));
mitems[i]=p;
printf("\n\t%d: %s",i+1, p);
printf("\n\t\t+++ %s",mitems[i]);
}
…..
per gli argomenti variabili nessun suggerimento?
io non ho capito se devi prendere n argomenti in numero e lunghezza variabile e memorizzarli in un array: è così?
marilynm69
04-04-2018, 21:08
io non ho capito se devi prendere n argomenti in numero e lunghezza variabile e memorizzarli in un array: è così?
esatto....per l'array e l'allocazione risolto, non capisco perchè mi inizia a prendere gli argomenti dal secondo
se faccio void addit(char *elems,...)
funziona come dovrebbe, ma a me serve passare argomenti prima, e per chiarezza un altro char * come titolo...
int main()
{
addit("FILE","new", "open", "save", "backup", "print", "setup", "exit", NULL);
return 0;
}
//---------------------------------------------------------------------------
void addit( char *title, char *elems ...)
{
va_list argP;
va_start(argP, elems);
char **mitems;
mitems=(char **)malloc(sizeof(char*));
char *p;
int i;
for (i=0; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=(char **)realloc(mitems,sizeof(mitems)+sizeof(*mitems));
mitems[i]=(char *)calloc(1, sizeof(char*));
mitems[i]=p;
printf("\n\t%d: %s",i+1, p);
printf("\n\t\t+++ %s",mitems[i]);
}
printf("\n\n%d arguments\n", i);
va_end(argP);
getchar();
}
//---------------------------------------------------------------------------
1: open
+++ open
2: save
+++ save
3: backup
+++ backup
4: print
+++ print
5: setup
+++ setup
6: exit
+++ exit
6 arguments
int main()
{
addit("FILE","new", "open", "save", "backup", "print", "setup", "exit", NULL);
return 0;
}
//---------------------------------------------------------------------------
void addit( char *title ...)
{
va_list argP;
va_start(argP, title);
char **mitems;
mitems=(char **)malloc(sizeof(char*));
char *p;
int i;
for (i=0; ((p=va_arg(argP, char*)) !=NULL) ; i++ )
{
mitems=(char **)realloc(mitems,sizeof(mitems)+sizeof(*mitems));
mitems[i]=(char *)calloc(1, sizeof(char*));
mitems[i]=p;
printf("\n\t%d: %s",i+1, p);
printf("\n\t\t+++ %s",mitems[i]);
}
printf("\n\n%d arguments\n", i);
va_end(argP);
getchar();
}
//---------------------------------------------------------------------------
1: new
+++ new
2: open
+++ open
3: save
+++ save
4: backup
+++ backup
5: print
+++ print
6: setup
+++ setup
7: exit
+++ exit
7 arguments
marilynm69
05-04-2018, 11:13
fosse solo un elenco che mi serve andrebbe bene, ma a me serve passare un puntatore a una struttura, il titolo a parte, e gli elementi un altra cosa...
ad esempio la funzione execl:
int execl (const char *__path, const char *__arg, ...)
come vedi sono 2 cose differenti path e arguments....a me serve title e gli elementi...in ogni caso, anche come hai fatto tu, dov'è finito "FILE"? un probabile utente si vedrà sparire la prima variabile, perchè mai?
anche semplificando tutto:
void addit(char * elems,...){
va_list argP;
va_start(argP, elems);
char *p;
int i;
for (i=0; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
printf("\n%s",p);
}
va_end(argP);
}
stampa da new:
new
open
save
backup
print
setup
exit
tolgo pure il ciclo for:
void addit(char * elems,...){
va_list argP;
va_start(argP, elems);
printf("\n%s",va_arg(argP,char*));
va_end(argP);
}
stampa " new " perchè? dove va a finire la prima variabile?
marilynm69
05-04-2018, 12:21
void addit(char * elems, ...){
va_list argP;
va_start(argP, elems);
printf("\n%s",elems);
printf("\n%s",va_arg(argP,char*));
va_end(argP);
}
la risolvo così, prendo elems come primo elemento, ci faccio il controllo se esiste almeno quello e continuo con il ciclo ,con va_start(argP, elems);
Grazie misterx per avermi portato comunque a risolverlo ;)
PS. devo mettere risolto nel titolo? se si come lo modifico?
però se si fa a questo modo, funziona come vuoi tu, invertendo i parametri della funzione
da così void addit(char *title, char *elems ...); a così void addit(char *elems, char *title ...);
void addit(char *elems, char *title ...);
int main()
{
addit("FILE","new", "open", "save", "backup", "print", "setup", "exit", NULL);
return 0;
}
//---------------------------------------------------------------------------
void addit(char *elems, char *title ...)
{
va_list argP;
va_start(argP, elems);
char **mitems;
mitems=(char **)malloc(sizeof(char*));
char *p;
int i;
for (i=0; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=(char **)realloc(mitems,sizeof(mitems)+sizeof(*mitems));
mitems[i]=(char *)calloc(1, sizeof(char*));
mitems[i]=p;
printf("\n\t%d: %s",i+1, p);
printf("\n\t\t+++ %s",mitems[i]);
}
printf("\n\n%d arguments\n", i);
va_end(argP);
getchar();
}
//---------------------------------------------------------------------------
sembra più un problema di posizione dei parametri
marilynm69
09-04-2018, 12:32
stessa cosa, comunque l'ho risolto così...ora il problema è un altro, ma il puntatore è puntatore a puntatore a struttura, e viene passato alla funzione addit per poi riallocare di volta in volta...non so se postarlo sempre quà, anche perchè il titolo sarebbe simile
#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;
}
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);
free(ml);
fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
return 0;
}
output terminale:
CHECK:MenuLabels has 0 menu
CHECK:MenuLabels has 1 menu
CHECK:MenuLabels has 2 menu
CHECK:MenuLabels has 2 menu
CHECK:MenuLabels has 2 menu
CHECK:MenuLabels has 2 menu
***END***
output Valgrind:
==13907== Memcheck, a memory error detector
==13907== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==13907== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==13907== Command: ./prove
==13907==
==13907== Invalid read of size 8
==13907== at 0x400812: addit (main.c:26)
==13907== by 0x400B27: main (main.c:75)
==13907== Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==13907== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13907== by 0x400855: addit (main.c:29)
==13907== by 0x400AF1: main (main.c:74)
==13907== Block was alloc'd at
==13907== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13907== by 0x40075C: ml_init (main.c:15)
==13907== by 0x400AB0: main (main.c:73)
==13907==
CHECK:MenuLabels has 0 menu
==13907== Invalid free() / delete / delete[] / realloc()
==13907== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13907== by 0x400855: addit (main.c:29)
==13907== by 0x400B27: main (main.c:75)
==13907== Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==13907== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13907== by 0x400855: addit (main.c:29)
==13907== by 0x400AF1: main (main.c:74)
==13907== Block was alloc'd at
==13907== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13907== by 0x40075C: ml_init (main.c:15)
==13907== by 0x400AB0: main (main.c:73)
==13907==
==13907== Invalid write of size 8
==13907== at 0x400882: addit (main.c:31)
==13907== by 0x400B27: main (main.c:75)
==13907== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==13907==
==13907==
==13907== Process terminating with default action of signal 11 (SIGSEGV)
==13907== Access not within mapped region at address 0x0
==13907== at 0x400882: addit (main.c:31)
==13907== by 0x400B27: main (main.c:75)
==13907== If you believe this happened as a result of a stack
==13907== overflow in your program's main thread (unlikely but
==13907== possible), you can try to increase the size of the
==13907== main thread stack using the --main-stacksize= flag.
==13907== The main thread stack size used in this run was 8388608.
CHECK:MenuLabels has 0 menu==13907==
==13907== HEAP SUMMARY:
==13907== in use at exit: 112 bytes in 4 blocks
==13907== total heap usage: 14 allocs, 10 frees, 1,392 bytes allocated
==13907==
==13907== 16 bytes in 1 blocks are definitely lost in loss record 2 of 4
==13907== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13907== by 0x400881: addit (main.c:31)
==13907== by 0x400B27: main (main.c:75)
==13907==
==13907== 96 (16 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
==13907== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13907== by 0x400855: addit (main.c:29)
==13907== by 0x400AF1: main (main.c:74)
==13907==
==13907== LEAK SUMMARY:
==13907== definitely lost: 32 bytes in 2 blocks
==13907== indirectly lost: 80 bytes in 2 blocks
==13907== possibly lost: 0 bytes in 0 blocks
==13907== still reachable: 0 bytes in 0 blocks
==13907== suppressed: 0 bytes in 0 blocks
==13907==
==13907== For counts of detected and suppressed errors, rerun with: -v
==13907== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
sembra ci sia un errore in mlabels=(MenuLabels **)realloc(mlabels,(j+2)*sizeof(MenuLabels*));
sono giorni che non ne esco...la parte tra i due commenti "/*+++...+++*/" è a posto
marilynm69
09-04-2018, 15:10
Risolto finalmente:yeah: ....ecco il codice:
#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[0]->title);
for (int i=0;ml[i]!=NULL ;i++ )
free(ml[i]);
fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
return 0;
}
unica cosa rimangono byte da deallocare che non capisco quali siano:
==18805== Memcheck, a memory error detector
==18805== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==18805== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==18805== Command: ./prove
==18805==
CHECK:MenuLabels has 0 menu
CHECK:MenuLabels has 1 menu
CHECK:MenuLabels has 2 menu
CHECK:MenuLabels has 3 menu
CHECK:MenuLabels has 4 menu
CHECK:MenuLabels has 5 menu
**********CHECK: FILE
***END***
==18805==
==18805== HEAP SUMMARY:
==18805== in use at exit: 56 bytes in 1 blocks
==18805== total heap usage: 52 allocs, 51 frees, 2,504 bytes allocated
==18805==
==18805== 56 bytes in 1 blocks are definitely lost in loss record 1 of 1
==18805== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18805== by 0x400858: addit (main.c:29)
==18805== by 0x400C33: main (main.c:79)
==18805==
==18805== LEAK SUMMARY:
==18805== definitely lost: 56 bytes in 1 blocks
==18805== indirectly lost: 0 bytes in 0 blocks
==18805== possibly lost: 0 bytes in 0 blocks
==18805== still reachable: 0 bytes in 0 blocks
==18805== suppressed: 0 bytes in 0 blocks
==18805==
==18805== For counts of detected and suppressed errors, rerun with: -v
==18805== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.