Fraunz81 Geschrieben 25. Oktober 2004 Geschrieben 25. Oktober 2004 Hallo! Bin neu in diesem Forum. Ich habe eine globale Struktur wie folgt deklariert: struct _DatensatzAE { unsigned int iGenre; //int-Wert des Genres in der Tabelle Filmtable unsigned int iVideo; //int-wert des Videoformats unsigned int iUser; //int-wert des Usernamen TCHAR *szpid; //id in Zeichen formuliert TCHAR *szpName; //Bezeichnung des Films TCHAR *szpFilmlength; //Länge des Films in Minuten TCHAR *szpVQuality; //Videoqualität des Films TCHAR *szpGenre; //Das Filmgenre TCHAR **szpSprache; //Array für die angegebenen Sprachen des Films TCHAR **szpAQuality; //Audioqualität der einzelnen Sprachen zum Film TCHAR **szpActor; //Array für die Schauspieler TCHAR *szpUser; //ausgewählte Besitzer aus der ListBox TCHAR *szpAnzahl; //Anzahl der Medien auf dem sich der Film befindet TCHAR *szpText; //Kurzbeschreibung zum Film } dsae = { 0, 0, 0, NULL, NULL, NULL, NULL, NULL , NULL, NULL, NULL, NULL, NULL, NULL}; In drei verschiedenen Funktionen stelle ich mittels malloc für diese TCHAR's Speicher zur Verfügung. (Die Daten frage ich von einer MySQL Datenbank ab. Es kann dadurch sein das einige Felder ein "\n" enthalten, was so viel heißt es ist leer.) Mein Problem bei der Sache ist, wenn ich wieder in eine Funktion zurückkehre, in der ich Speicher alokieren möchte, gebe ich den Speicher für die einzelnen Elemente wieder frei. Hier liegt das Problem, wenn ich szpAnzahl freigebe funkt es noch, wenn ich dann in weiterer folge szpText freigeben will stürzt mein Programm mit Access Violation (0xC0000005) ab. Gebe ich jedoch den Speicher der einelnen Elemente noch bevor die Funktion zuende ist wieder frei funktioniert die free-Anweisung. Ich brauche die Daten jedoch noch in einer Anderen Funktion. Wenn jemand eine Erklärung dazu hätte wäre das ganz toll. Danke. PS.: Die Elemente werden nicht der Reihe nach, so wie sie in der Struct aufgelistet sind, mit malloc/free alokiert/freigeben. Zitieren
Guybrush Threepwood Geschrieben 25. Oktober 2004 Geschrieben 25. Oktober 2004 Dieser Fehler tritt oft auf wenn du über den von dir reservierten Speicher rausschreibst. Also platz für 10 Zeichen reserviert und 11 reingeschrieben. Oder wenn du versuchst einen NULL Zeiger freizugeben. Zitieren
Klotzkopp Geschrieben 25. Oktober 2004 Geschrieben 25. Oktober 2004 Oder wenn du versuchst einen NULL Zeiger freizugeben. Nullzeiger freigeben tut nichts. @Fraunz81: Warum verwendest du keine Stringklasse anstatt der TCHAR-Zeiger? Dann müsstest du dich nicht mehr um die Speicherverwaltung kümmern. Zitieren
Guybrush Threepwood Geschrieben 25. Oktober 2004 Geschrieben 25. Oktober 2004 Nullzeiger freigeben tut nichts. Stimmt ich meinte eigentlich einen uninitialisierten. Zitieren
Fraunz81 Geschrieben 25. Oktober 2004 Autor Geschrieben 25. Oktober 2004 Ich glaube zwar nicht das ich zu wenig Speicher reserviert habe, da das freigeben funktioniert wenn ich die Elemente in der selben Funktion zum Schluss noch freigebe. Aber das könnte ich heute abend bzw. morgen dann noch mal testen. Das Problem tritt erst auf wenn ich wieder in diese Funktion zurückkehre und dann erst die Elemente freigebe, bevor ich ein weiteres Mal Speicher alokiere. Beispiel: funktion1() { //wenn vor dem malloc freigeben wird, funkt es nicht if (dsae.szpAnzahl != NULL) { free(...); ...szpAnzahl = NULL; } //funkt noch if (dsae.szpText != NULL) { free(...); //dieser Aufruf verursacht den Crash ...szpText = NULL; } //funkt noch //hier werden für die Elemente //szpid, szpName, szpFilmlength, szpVQuality, szpGenre, szpUser, //szpAnzahl, szpText mit malloc Speicher reserviert //wenn hier freigegeben wird funkt es } funktion2() { //hier werden für die Elemente //szpSprache, szpQuality //mit malloc Speicher reserviert } funktion3() { //hier werden für die Elemente //szpActor //mit malloc Speicher reserviert } funktion4() { //Wird der Button gedrückt werden die drei Funktionen aufgerufen funktion1(); funktion2(); funktion3(); //Verarbeitung der Daten } Die String Klasse will ich nicht verwenden, da ich mich zu wenig damit beschäftige und ich mit den Pointern mehr vertraut machen will. Danke für die schnellen Antworten. Zitieren
Fraunz81 Geschrieben 3. November 2004 Autor Geschrieben 3. November 2004 Hat noch jemand eine Idee was falsch sein kann?? Kann es daran liegen dass eine Struktur einen zusammenhängenden Speicher benötigt? Ich habe gelesen das ein Windowsprogramm nur einen 1MB grossen HEAP - Speicher zugewiesen bekommt und ich vielleicht schon zu viel reserviert habe und dadurch nicht den ganzen Speicher wieder freigeben kann. Wenn ja, wie reserviere ich einen zweiten HEAP - Speicher unter Windows XP. Oder ist das SP2 von Windows XP schuld? Hat sich irgend etwas geändert, was ich nicht berücksichigt habe? Vielleicht wisst ihr ein paar Internetseiten wo ich nachlesen könnte? Zitieren
Klotzkopp Geschrieben 3. November 2004 Geschrieben 3. November 2004 Hat noch jemand eine Idee was falsch sein kann?? Du lieferst einfach nicht genug Informationen, als dass man dir helfen könnte. Kann es daran liegen dass eine Struktur einen zusammenhängenden Speicher benötigt?Nein. Ich habe gelesen das ein Windowsprogramm nur einen 1MB grossen HEAP - Speicher zugewiesen bekommt und ich vielleicht schon zu viel reserviert habe und dadurch nicht den ganzen Speicher wieder freigeben kann.Der Stack ist normalerweise 1 MB groß. Der hat mit dynamischem Speicher nichts zu tun. Es bringt nichts, den Heap zu vergrößern. Du hast einen Speicher-Bug in deinem Programm, den musst du finden. Ich vermute den Fehler irgendwo in " //Verarbeitung der Daten". Solange du aber nicht sagst, was da passiert (mit Code), können wir nur raten. Es wäre wirklich am einfachsten, eine String-Klasse zu verwenden. Die sind genau dafür da, dass du dich nicht mit dynamischem Speicher herumschlagen musst. Zitieren
Fraunz81 Geschrieben 3. November 2004 Autor Geschrieben 3. November 2004 In der Verarbeitung der Daten wird es nicht liegen. (funktion void data_copy_to_controls(HWND hDSAEDlg) ) Habe ich deshalb wegelassen, da ich sonst nicht unter die 10000 Zeichen kommen. Ich entschulidge mich gleich für den Programmierstil und die Unübersichtlichkeit search_filmtable_id in dieser Funktion tritt der Fehler auf wenn man in diese das zweite Mal dann wieder aufruft um den Speicher wieder freizugeben und neu zu alokieren. BOOL CALLBACK DatensatzAEDlg(HWND, UINT, WPARAM, LPARAM); //Funktionen zum suchen der angeforderten Daten im "Datensatz ändern"-Dialog void search_filmtable_id(HWND); void search_audiotable_id(); void search_schauspieler_id(); void data_copy_to_controls(HWND); void search_filmtable_id(HWND hDSAEDlg) { unsigned long anzahl_reihen = 0; unsigned int i = 0; int iIndex = 0, iLength = 0; MYSQL_ROW row; MYSQL_RES *mysql_res; char *query; //*string; char *select = "SELECT * FROM filmtable WHERE id = "; HWND hwndDSAE = NULL; //Handle zu IDC_CHANGE_ID ermitteln //ListBox szpid hwndDSAE = GetDlgItem(hDSAEDlg, IDC_CHANGE_ID); //Prüfen, ob IDC_ADD_OWNER Listbox text enthält if ((iIndex = SendMessage(hwndDSAE, LB_GETCURSEL, 0, 0)) >= 0) { iLength = SendMessage(hwndDSAE, LB_GETTEXTLEN, iIndex, 0); if (dsae.szpid != NULL) { free(dsae.szpid); dsae.szpid = NULL; } dsae.szpid = (TCHAR *) malloc(sizeof(TCHAR) * (iLength + 1)); SendMessage(hwndDSAE, LB_GETTEXT, iIndex, (LPARAM) dsae.szpid); } query = (char *) malloc(strlen(select) + strlen(dsae.szpid) + 1); strcpy(query, select); strcat(query, dsae.szpid); /* Jetzt die Anfrage an den Datenbankserver */ mysql_query(mysql, query); check_error(); /* Daten der Anfrage abholen */ mysql_res = mysql_store_result(mysql); check_error(); /* Anzahl der gefundenen Datensätze ermitteln */ anzahl_reihen = (unsigned long) mysql_num_rows (mysql_res); //printf ("Anzahl gefunden: %lu\n\n", anzahl_reihen); /* Gefundener Datensatz bzw. Datensätze ausgeben */ while ((row = mysql_fetch_row (mysql_res)) != NULL) { /* Einzelne Spalten der Zeile ausgeben */ for (i = 0; i < mysql_num_fields(mysql_res); i ++) switch(i) { case 0: //Hier kann man die ID erfassen break; case 1: //printf ("%60s ",row[i]); //Filmbezeichnung if (dsae.szpName != NULL) { free(dsae.szpName); dsae.szpName = NULL; } dsae.szpName = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(dsae.szpName, "%s", row[i]); break; case 2: //printf ("%5s ",row[i]); //Filmlänge if (dsae.szpFilmlength != NULL) { free(dsae.szpFilmlength); dsae.szpFilmlength = NULL; } dsae.szpFilmlength = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(dsae.szpFilmlength, "%s", row[i]); break; case 3: //printf ("%5s ",row[i]); //VideoformatID //dsae.szpVQuality = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); if (dsae.szpVQuality != NULL) { free(dsae.szpVQuality); dsae.szpVQuality = NULL; } //wsprintf(dsae.szpVQuality, "%s", row[i]); dsae.iVideo = str2int(row[i]); dsae.szpVQuality = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(*(video.format + (dsae.iVideo - 1))) + 1)); wsprintf(dsae.szpVQuality, "%s", *(video.format + (dsae.iVideo - 1))); break; case 4: //printf ("%5s ",row[i]); //FilmartID //dsae.szpGenre = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); //wsprintf(dsae.szpGenre, "%s", row[i]); if (dsae.szpGenre != NULL) { free(dsae.szpGenre); dsae.szpGenre = NULL; } dsae.iGenre = str2int(row[i]); if (dsae.iGenre) { MessageBox(NULL, row[i], TEXT("In der If Anweisung Genre"), MB_OK); dsae.szpGenre = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(*(genre.art + dsae.iGenre - 1)) + 1)); wsprintf(dsae.szpGenre, "%s", *(genre.art + dsae.iGenre - 1)); } else break; case 5: //printf ("%5s ",row[i]); //BesitzerID //dsae.szpUser = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); //wsprintf(dsae.szpUser, "%s", row[i]); if (dsae.szpUser != NULL) { free(dsae.szpUser); dsae.szpUser = NULL; } dsae.iUser = str2int(row[i]); //MessageBox(NULL, row[i], TEXT("UserID"), MB_OK); //MessageBox(NULL, *(besitzer.user + dsae.iUser - 1), TEXT("User"), MB_OK); dsae.szpUser = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(*(besitzer.user + dsae.iUser - 1)) + 1)); wsprintf(dsae.szpUser, "%s", *(besitzer.user + dsae.iUser - 1)); break; case 6: //printf ("%5s ",row[i]); //Medienanzahl if (dsae.szpAnzahl != NULL) { free(dsae.szpAnzahl); //dieses free funktioniert dsae.szpAnzahl = NULL; } //dsae.iA = str2int(row[i]); dsae.szpAnzahl = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(dsae.szpAnzahl, "%s", row[i]); break; case 7: //printf ("%50s ",row[i]); //Kurzbeschreibung if (dsae.szpText != NULL) { free(dsae.szpText); //dieses free funktioniert nicht mehr???? dsae.szpText = NULL; } if (row[i] != "") { dsae.szpText = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(dsae.szpText, "%s", row[i]); //strcpy(dsae.szpText, row[i]); } else break; } //printf("\n"); } /* free(dsae.szpFilmlength); dsae.szpFilmlength = NULL; free(dsae.szpName); dsae.szpName = NULL; free(dsae.szpAnzahl); dsae.szpAnzahl = NULL; free(dsae.szpText); dsae.szpText = NULL; */ /* Speicherplatz wieder freigeben */ mysql_free_result(mysql_res); // free(string); free(query); } void search_audiotable_id() { unsigned long anzahl_reihen; unsigned int i = 0, j = 0; MYSQL_ROW row; MYSQL_RES *mysql_res; char *query; //, *string; char *select = "SELECT * FROM audiotable where audiospurenid ="; query = (char *) malloc(strlen(select) + strlen(dsae.szpid) + 1); strcpy(query, select); strcat(query, dsae.szpid); /* Jetzt die Anfrage an den Datenbankserver */ mysql_query(mysql, query); check_error(); /* Daten der Anfrage abholen */ mysql_res = mysql_store_result(mysql); check_error(); /* Anzahl der gefundenen Datensätze ermitteln */ anzahl_reihen = (unsigned long) mysql_num_rows (mysql_res); dsae.szpSprache = (TCHAR **) malloc(sizeof(TCHAR *) (anzahl_reihen + 1)); dsae.szpAQuality = (TCHAR **) malloc(sizeof(TCHAR *) (anzahl_reihen + 1)); //printf ("Anzahl gefunden: %lu\n\n", anzahl_reihen); /* Gefundener Datensatz bzw. Datensätze ausgeben */ while ((row = mysql_fetch_row (mysql_res)) != NULL) { /* Einzelne Spalten der Zeile ausgeben */ for (i = 0; i < mysql_num_fields(mysql_res); i++) { switch(i) { case 0: //Hier kann man die AudiospurenID erfassen break; case 1: //printf ("%60s ",row[i]); //Audiospuren *(dsae.szpSprache + j) = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(*(dsae.szpSprache + j), "%s", row[i]); break; case 2: //printf ("%5s ",row[i]); //Audioqualität *(dsae.szpAQuality + j) = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(*(dsae.szpAQuality + j), "%s", row[i]); break; } //printf("\n"); } j++; } *(dsae.szpSprache + anzahl_reihen) = NULL; *(dsae.szpAQuality + anzahl_reihen) = NULL; /* Speicherplatz wieder freigeben */ mysql_free_result(mysql_res); // free(string); free(query); } void search_schauspieler_id() { unsigned long anzahl_reihen; unsigned int i = 0, j = 0; MYSQL_ROW row; MYSQL_RES *mysql_res; char *query; //, *string; char *select = "SELECT * FROM schauspieler where hauptdarstellerid ="; query = (char *) malloc(strlen(select) + strlen(dsae.szpid) + 1); strcpy(query, select); strcat(query, dsae.szpid); /* Jetzt die Anfrage an den Datenbankserver */ mysql_query(mysql, query); check_error(); /* Daten der Anfrage abholen */ mysql_res = mysql_store_result(mysql); check_error(); /* Anzahl der gefundenen Datensätze ermitteln */ anzahl_reihen = (unsigned long) mysql_num_rows (mysql_res); dsae.szpActor = (TCHAR **) malloc(sizeof(TCHAR *) (anzahl_reihen + 1)); //printf ("Anzahl gefunden: %lu\n\n", anzahl_reihen); /* Gefundener Datensatz bzw. Datensätze ausgeben */ while ((row = mysql_fetch_row (mysql_res)) != NULL) { /* Einzelne Spalten der Zeile ausgeben */ for (i = 0; i < mysql_num_fields(mysql_res); i ++) { switch(i) { case 0: //Hier kann man die HaupdarstellerID erfassen break; case 1: //printf ("%60s ",row[i]); //Hauptdarsteller *(dsae.szpActor + j) = (TCHAR *) malloc(sizeof(TCHAR) * (strlen(row[i]) + 1)); wsprintf(*(dsae.szpActor + j), "%s", row[i]); break; } //printf("\n"); } j++; } *(dsae.szpActor + anzahl_reihen) = NULL; /* Speicherplatz wieder freigeben */ mysql_free_result(mysql_res); // free(string); free(query); } Zitieren
Klotzkopp Geschrieben 3. November 2004 Geschrieben 3. November 2004 Mir sind zwei Dinge aufgefallen: if (row[i] != "") Das funktioniert nicht so, wie du es vermutest, falls row ein char-Pointer ist, was ich vermute. Du könntest auf != NULL testen, oder strcmp verwenden. Zweitens kannst du dir die Abfrage auf != NULL sparen, wenn du free aufrufst. Kannst du soviel wie möglich aus dem Code rauswerfen, so dass der Fehler immer noch auftritt? Zitieren
Fraunz81 Geschrieben 3. November 2004 Autor Geschrieben 3. November 2004 if (row != "") Anfangs dachte ich das dieser Wert NULL ist jedoch wird ein Leerzeichen übergeben. Warum kann ich mir die Abfrage != NULL sparen wenn ich free aufrufe? Ich dachte, wenn ich zweimal einen Speicherbereich freigebe bzw. wenn noch kein Speicherbereich mit malloc alokiert wurde, kann es zu Probleme kommen. Kannst du soviel wie möglich aus dem Code rauswerfen, so dass der Fehler immer noch auftritt? Ich werde versuchen so viel Code als möglich herauszunehmen und poste den Code morgen dann nochmal. Hoffentlich stolper ich über diesen Fehler und kann das entgültig korrigieren. Wer in seine C, C++ Programme MySQL verwenden will der findet auf folgender Seite gute infos: http://pronix.de/modules/C/openbook/ Zitieren
Klotzkopp Geschrieben 3. November 2004 Geschrieben 3. November 2004 Anfangs dachte ich das dieser Wert NULL ist jedoch wird ein Leerzeichen übergeben.Sicher ein Leerzeichen, kein Leerstring? Aber selbst dann kannst du nicht mit != vergleichen, du musst strcmp benutzen. Warum kann ich mir die Abfrage != NULL sparen wenn ich free aufrufe? Ich dachte, wenn ich zweimal einen Speicherbereich freigebe bzw. wenn noch kein Speicherbereich mit malloc alokiert wurde, kann es zu Probleme kommen. Wenn du den Zeiger nach dem free auf NULL setzt, kannst du doch gar nicht mehr doppelt freigeben. Und du setzt doch am Anfang alle Zeiger auf NULL, oder? free(NULL) tut nichts. Darum ist die Abfrage für den free-Aufruf sinnlos. Zitieren
Fraunz81 Geschrieben 4. November 2004 Autor Geschrieben 4. November 2004 Gestern habe ich meine Fehler gefunden. Wer ein wenig rätseln will wo der Fehler ist, hier die fehlerhaften Anweisungen: dsae.szpSprache = (TCHAR **) malloc(sizeof(TCHAR *) (anzahl_reihen + 1)); dsae.szpAQuality = (TCHAR **) malloc(sizeof(TCHAR *) (anzahl_reihen + 1)); dsae.szpActor = (TCHAR **) malloc(sizeof(TCHAR *) (anzahl_reihen + 1)); Und hier die korrigierte Version: dsae.szpSprache = (TCHAR **) malloc(sizeof(TCHAR *) [B]*[/B] (anzahl_reihen + 1)); dsae.szpAQuality = (TCHAR **) malloc(sizeof(TCHAR *) [B]*[/B] (anzahl_reihen + 1)); dsae.szpActor = (TCHAR **) malloc(sizeof(TCHAR *) [B]*[/B] (anzahl_reihen + 1)); Warum mir der VC6 - Compiler (Autorenversion) da keinen Fehler gemeldet hat, verstehe ich nicht ganz. Hat der Compiler bei den hier gezeigten Anweisungen eine Typumwandlung druchführen wollen??? Und warum hat er bei der Speicherbelegung nicht schon einen Fehler gemeldet??? Mein CBuilderX - Compiler von Borland hat mit dem Fehler "Nicht-Funktion" die Compilierung beendet. Auf jeden Fall vielen Dank an Klotzkopp, du hast mich auf die Idee gebracht die anderen 2 Funktionen heraus zu nehmen. :uli Zitieren
Klotzkopp Geschrieben 4. November 2004 Geschrieben 4. November 2004 Anscheinend ist das ein Bug in Visual C++ 6. Der Compiler akzeptiert das hier: int x = sizeof(char*) 3; Dabei wird die 3 komplett ignoriert. Visual C++ 7.1 gibt eine Fehlermeldung aus. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.