Zum Inhalt springen

Dynamische Elemente in einer struct


Fraunz81

Empfohlene Beiträge

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 Wochen später...

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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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);

}

Link zu diesem Kommentar
Auf anderen Seiten teilen

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?

Link zu diesem Kommentar
Auf anderen Seiten teilen

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/

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...