realloc in Unterfunktion

Kojac

Grünschnabel
Hi,

ich hänge momentan an einem Problem und komme nicht weiter.
Ich versuche, in meinem Programm eine Ini-Datei auszulesen und die ausgelesenen Werte abzuspeichern.

Von der Idee her find ich das auch ganz einfach umzusetzen, nur diese ganze Pointernotation macht mir echt zu schaffen. Ich muss dazu sagen, dass ich inzwischen ca 5-6 Jahre kein C mehr programmiert habe und daher immer wieder auf Probleme stoße, der Großteil davon hat mit Zeigern zu tun.

Meine gedachte Vorgehensweise zum Auslesen eines Ini-Keys ist folgende:

- Im Main deklariere ich einen char*, der auf den späteren String zeigen soll
- Diesen Zeiger übergebe ich an eine Unterfunktion, die mir das Ini-File auslesen soll
- Ich lese den Schlüssel der Inidatei in einen Puffer aus (GetPrivateProfileString)
- Die Länge des resultierenden Arrays im Puffer wird für ein realloc in der Unterfunktion verwendet, um den ursprünglichen Zeiger mit Speicher zu versehen
- Der String des Schlüssels wird in den neu alloziierten Speicher geschrieben
- Die Unterfunktion wird beendet
- Nach Verarbeitung des Schlüssels wird der alloziierte Speicher mit free wieder freigegeben

Ich habe dies probiert und es gab logischerweise einen Stack corrupt, weil ich höchstwahrscheinlich nur ein Call-by-Value gemacht hab und daher mein umalloziierter Chararray lokal war und danach dann wieder gelöscht wurde.

Hier der Code dazu:

void GetIniString(char* Section, char* Key, char* IniPath, char* StringArray) {
char KeyReadingBuffer[255];

GetPrivateProfileString(Section, Key, NULL, KeyReadingBuffer, 254, IniPath);
StringArray = (char*)realloc(StringArray, (strlen(KeyReadingBuffer)*sizeof(char)));
strncpy(StringArray, KeyReadingBuffer, strlen(KeyReadingBuffer));
StringArray[strlen(KeyReadingBuffer)] = '\0';

return;
}

Aufruf mit:
GetIniString("Section", "Key", IniPath, StringArray);
free(StringArray);


Daher habe ich probiert, den char* vom Main per Call-by-reference zu übergeben und in der Unterfunktion über den Zeiger auf den ursprünglichen Zeiger zuzugreifen.
Dabei verrenne ich mich aber hilflos in * und & Zeichen, weil ich nie weiß, wann ich was brauche.

Analog zu diesem Problem versuche ich das auch noch mit einer Matrix, um eine ganze Section per GetPrivateProfileSection auszulesen und dann abzuspeichern.

Kann mir da jemand ein wenig weiterhelfen, damit ich mal den richtigen Weg finde?

Danke für die Hilfe.

Gruß,
Joe
 
Hi.

Es ist ja alles ganz nett, das du beschreibst was du (vermutlich) programmiert haben willst. Aber warum zeigst du nicht einfach den Code anstatt ihn unzureichend zu beschreiben?

Mach einfach mal ein einfaches, compilierbares Beispiel was das Problem aufzeigt (und verwende bitte Code-Tags - also C Code bitte in [c]...[/c] und C++ in [code=cpp]...[/code] Tags einfügen).

Du weißt schon, das du erst ein realloc machen kannst wenn du vorher den Speicher mit malloc alloziert hast?

Gruß
 
Hi,

ja, ich weiß, dass ich erst Speicher allokieren muss, bevor ich ihn umbauen kann. Und meiner Meinung nach habe ich das auch getan.

Hier jetzt mal der vollständige Code:

C:
#include <stdio.h>
#include <string.h>
#include <direct.h>
#include <windows.h>

#define MaxIniKeyLength 30
#define MaxIniKeyNumber 10

void GetFullIniPath(char* IniPath);
void GetIniString(char* Section, char* Key, char* IniPath, char* (*StringArray));
void SetIniString(char* Section, char* Key, char* Value, char* IniPath);
short GetIniSection(char* Section, char* IniPath, char** (*SectionMatrix));
void Free(char* (*StringArray));
void Free(char** (*SectionMatrix), short NumberOfRows);

int main(int argc, char** argv)
{
	char IniPath[60],
		*StringArray = (char*)(malloc(sizeof(char))),
		**SectionMatrix = (char**)(malloc(sizeof(char*)));
	int i;
	short NumberOfRows;

	StringArray[0] = '\0';

	GetFullIniPath(IniPath);

	GetIniString("Modules", "Module1", IniPath, &StringArray);
	printf("Read ini key: %s\n", StringArray); // Funktioniert
	Free(&StringArray);

	NumberOfRows = GetIniSection("Modules", IniPath, &SectionMatrix);
	for (i = 0; i < NumberOfRows; i++)
	{
		printf("Keys of section: %s\n", SectionMatrix[NumberOfRows]); // ergibt einen Fehler
	}

	Free(&SectionMatrix, NumberOfRows);

	return 0;
}

void GetFullIniPath(char* IniPath)
{
	_getcwd(IniPath, 60);
	strncat(IniPath, "\\ini.ini", 8);
	return;
}

void GetIniString(char* Section, char* Key, char* IniPath, char* (*StringArray))
{
	char KeyReadingBuffer[255];

	GetPrivateProfileString(Section, Key, NULL, KeyReadingBuffer, (MaxIniKeyLength-1), IniPath);

	StringArray[0] = (char*)realloc(StringArray[0], ((strlen(KeyReadingBuffer)+1)*sizeof(char)));

	strncpy((*StringArray), KeyReadingBuffer, strlen(KeyReadingBuffer));
	(*StringArray)[strlen(KeyReadingBuffer)] = '\0';

	return;
}

void SetIniString(char* Section, char* Key, char* Value, char* IniPath)
{
	WritePrivateProfileString(Section, Key, Value, IniPath);
	return;
}

short GetIniSection(char* Section, char* IniPath, char** (*Matrix))
{
	size_t OldEnd, NewEnd;
	short MatrixRow;
	char KeyReadingBuffer[255],
		 *Result;

	GetPrivateProfileSection(Section, KeyReadingBuffer, 254, IniPath);

	OldEnd = NewEnd = 0;
	while (1)	// neverending loop
	{
		NewEnd = strlen(KeyReadingBuffer);
		if (NewEnd - OldEnd == 1)	// detection of the 2 '\0' at the end of the array
			break;
		KeyReadingBuffer[NewEnd] = '\t';	// replace the first '\0' by a '\t'
		OldEnd = NewEnd;	// save last appearance of a '\0'
	}

	MatrixRow = 0;
	Result = strtok( KeyReadingBuffer, "\t" );
	while( Result != NULL )
	{
		if (MatrixRow)
		{
			Matrix[0] = (char**)(realloc(Matrix[0], (MatrixRow+1)*sizeof(char*)));
		}

		Matrix[0][MatrixRow] = (char*)(calloc((strlen(Result)+1), sizeof(char)));

		strncpy(Matrix[0][MatrixRow], Result, strlen(Result));
		Matrix[0][MatrixRow][strlen(Result)] = '\0';
		MatrixRow++;
		/* Get next token: */
		Result = strtok( NULL, "\t");
	}

	return (MatrixRow);
}

void Free(char* (*Array))
{
	if (*Array != NULL)
		free(*Array);
	return;
}

void Free(char** (*Matrix), short NumberOfRows)
{
	int i;

	for (i = 0; i < NumberOfRows; i++)
		if ((*Matrix)[i] != NULL)
			free((*Matrix)[i]);
	if ((*Matrix) != NULL)
		free((*Matrix));
	return;
}

Die Verarbeitung eines einzelnen Ini-Schlüssels funktioniert ohne Fehler, die einer ganzen Sektion nicht.
Da ich denke, dass ich beide auf dem selben Prinzip aufgebaut habe, könnte es auch eher ein Zufall sein, dass das erste läuft.

Gruß
 
Servus,

oh man wie dämlich kann man sich eigentlich anstellen? Ich hab da mindestens 1 Million mal draufgeschaut und es ist mir nicht aufgefallen. Liegt wohl daran, dass ich das mal als Laufparameter hatte, bevor ich i benutzt hab.

Auf alle Fälle danke für die schnelle Hilfe.

Viele Grüße


P.S.: Nur weil ich da 2-3 c++ Funktionen hab, macht das den restlichen Code noch lange nicht zum c++-Code. ;)
 

Neue Beiträge

Zurück