char ** wieder richtig freigegeben?



  • Hi leutz,
    als erstes, sehr geiles forum hier, hat mir bereits sehr gut geholfen.
    Jetzt habe ich aber ein Problem bei dem ich mir nicht sicher bin, ob es wirklich ein problem ist oder nicht.

    void mysql_finde_feld(MYSQL *mysql, char *table_name)
    {
    	int i,zeilen_anzahl;
    	char *query;
    	char **temp;					///////unbeding besseren namen einfallen lassen...
    	unsigned long query_length;
    	MYSQL_RES *result;
    	MYSQL_ROW row;
    
    	query_length=strlen("explain ")+strlen(table_name)+1;
    	query=(char *)malloc(query_length);
    	strcpy(query,"explain ");
    	strcat(query,table_name);
    	mysql_real_query(mysql,query,query_length);
    	mysql_check_error(mysql);
    	result=mysql_store_result(mysql);
    	mysql_check_error(mysql);
    
    	zeilen_anzahl=mysql_num_rows(result);
    	temp=(char **)malloc(zeilen_anzahl);
    
    	for(i=0;i<zeilen_anzahl;i++)
    	{
    		row=mysql_fetch_row(result);
    		temp[i]=(char *)malloc(strlen(row[0]));
    		strcpy(temp[i],row[0]);
    	}
    
    	for(i=0;i<zeilen_anzahl;i++)
    	{
    		printf("-%i- %s \n",i,temp[i]);
    	}
    	printf("-%i- ENDE",i);
    
    	printf("\n");
    	free(*temp);
    	free(temp);
    	free(query);
    }
    

    Der obige code soll alle feldnamen einer tabelle auslesen und in einem array von chars speichern und nen menü draus bauen (kommt nocht).
    funzt soweit auch alles ganz gut, ich bin mir aber nicht sicher, ob ich das char ** wieder richtig freigegeben habe. Sprich muss ich noch mehr freigeben (also jedes (char *)element einzeln und dann das gesamte (char **) oder reicht es wenn ich nur das (char **) wieder freigebe? ich mein meine windose läuft auch so schon instabli genug, ohne nen haufen speicherleichen von mir 😃 .
    schon mal danke, für alle die da hilfreiche tipps haben (wo es im i-net sonst evtl stehen könnte is ja auch nen tipp...aber google und die forumshilfe habe ich bereits erfolglos bemüht)

    der Flo



  • du musst ein 2 dimensionales array in umgekehrter reihenfolge wie du es erstellt hast wieder freigeben.
    Sprich erst alle Elemente in der 2. dimension (die du per schleife erzeugt hast)
    dann dann die 1. dimension.

    int i;
    char **array;
    
    array = (char**)malloc (10);
    
    for (i = 0; i < 10; i++)
    {
        array[i] = (char*)malloc(100);
    }
    
    // freigabe
    for (i = 0; i < 10; i++)
    {
        free (array[i]);
    }
    free(array);
    


  • Alles klar, danke schön.
    Hat sich damit dann erledigt.

    mfg Flo



  • hmm, irgendwie wars das doch nicht so wirklich, hatte augenscheinlich funktioniert (im PellesC) bei kleinen werten. Bei großen werten gabs nen schicken abflug bei der speicherfreigabe. Habe den ganzen sims mal durch den MSVisual c++ 6.0 gejagt, hat auch ordentlich kompiliert, gab jedoch die gleichen abflüge bei dem free(temp[i]). Jetzt habe ich mal folgenden test-code kompiliert(ohne fehler im MS) jedoch führt der nichtmal einen free(test[i]) aus sondern schmiert beim ersten free(test[i]) ab.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int i;
        char **test;
    
        //speicher besorgen
        test=(char**)malloc(10);
        for(i=0;i<10;i++)
        {
            test[i]=(char*)malloc(100);
        }
    
        //speicher freigeben
        for(i=0;i<10;i++)
        {
            free(test[i]);
        }
        free(test);
    }
    

    Da ich bereits mehrere andere versuche der Speicherfreigabe erfolglos versucht habe bin ich langsam am verzweifeln.



  • Du musst bei malloc schon die Größe des Typs berücksichtigen, nur bei [[un]signed] char kannst du das weglassen.

    Und lass die Casts weg:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main(void)
    {
        int i;
        char **test;
    
        //speicher besorgen
        test=malloc(10*sizeof(char*));
        for(i=0;i<10;i++)
        {
            test[i]=malloc(100);
        }
    
        //speicher freigeben
        for(i=0;i<10;i++)
        {
            free(test[i]);
        }
        free(test);
    }
    


  • Ja, das wars, es lag an der vergessenen Größe. Jetzt funktioniert es sicher.
    Vielen Dank.
    Was ich aber nicht ganz verstehe ist die sache mit den casts, warum soll ich die weglassen?
    malloc() liefert doch (void 😉 zurück und ich brauche doch aber (char **) bzw. (char *). Sollte ich da nicht nen explizizten typecast vornehmen 😕

    Aber wie gesagt, so funktioniert es, vielen Dank.

    mfg Flo



  • der_flo_gast schrieb:

    Was ich aber nicht ganz verstehe ist die sache mit den casts, warum soll ich die weglassen?
    malloc() liefert doch (void 😉 zurück und ich brauche doch aber (char **) bzw. (char *). Sollte ich da nicht nen explizizten typecast vornehmen 😕

    In C ist ein void* implizit in jeden anderen Zeigertyp konvertierbar.

    In C++ ist das übrigens nicht so. Man sieht solche Cast oft bei Leuten, die ihren C-Code durch einen C++-Compiler jagen.



  • Alles klar, vielen dank für die Erlärung.

    Aber da C eine Untermenge con C++ darstellt, sollte es dann nicht auch in C++ funktionieren mit dem impliziten typecast, oder ist es Compilerabhängig?
    Ist zwar nicht mehr Problem relevant, würde mich aber dennoch interessieren. Über nen Link oder nen google-Denkanstoß würden ich mich freuen.

    mfg Flo



  • verkehrt ist der explizite cast nicht aber im falle von C nicht notwendig.



  • der_flo_gast schrieb:

    Aber da C eine Untermenge con C++ darstellt, sollte es dann nicht auch in C++ funktionieren mit dem impliziten typecast, oder ist es Compilerabhängig?

    C stellt keine Untermenge von C++ dar.



  • hmm,
    ich dachte bisher immer, dass C vollständig in C++ vorhanden ist und somit eine untermenge von c++ darstellt. Aber ich lass mich gerne eines besseren belehren.

    Vielen Dank an alle Antworten,

    mfg Flo



  • Das C in C++ vollständig enthalten ist, stimmt nicht. Das C aber quasi vollständig in C++ enthalten ist, stimmt sehr wohl.
    (LordJaxom hat halt eine grosse Liebe zum Detail.)



  • ROTOR schrieb:

    Das C in C++ vollständig enthalten ist, stimmt nicht. Das C aber quasi vollständig in C++ enthalten ist, stimmt sehr wohl.
    (LordJaxom hat halt eine grosse Liebe zum Detail.)

    Beides wahr. Aber immerhin geht es hier um eines dieser Details (und diese Details fliegen Leuten, die mit beiden Sprachen parallel arbeiten müssen regelmäßig um die Ohren) 😉



  • Ist ja vollkommen richtig, und ich als Anfänger bin sehr froh, dass es diese forum gibt, und das ihr einen eben auch auf solche spitzfindigkeiten aufmerksam macht.
    In der Literatur, die ich bisher gelesen habe, hieß es immer c sei vollständig in c++ enthalten, was ja auch bis zu einem bestimmten punkt stimmt aber eben nicht 100% richtig ist.
    Bin Anwendungsentwickler AZUBI im 1. Jahr und da wird einem selbst in der Schule erzählt, dass c zu 100% in c++ enthalten ist, was ja nun so nicht stimmt.
    Wenn ich das richtig verstanden habe ist in c ein void* implizit in jeden <datentyp>* konvertierbar ist in c++ hingegen nicht.

    mfg Flo


Anmelden zum Antworten