"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

[C] (falsche?) Verwendung von strncat - Ergebnis verursacht "Bus error"

Mr. Zet 10.11.2007 - 00:50 990 8
Posts

Mr. Zet

Super Moderator
resident spacenerd
Avatar
Registered: Oct 2000
Location: Edge of Tomorrow
Posts: 12040
Bin gerade am Verzweifeln, verwöhnt von den annehmlichkeiten von Java, dachte ich nicht, dass ich an so etwas "trivialem" wie Stringverkettung scheitern könnte... :(

folgende funktion:
Code:
/*
 * AllocateResources() opens the files to read from
 *
 * Arguments: filename1, filename2 - the files to open
 */
void AllocateResources(const char *filename1, const char *filename2)
{
	
	char *emsg;

	/* open first file */
	if ((file1 = fopen(filename1, "r")) == NULL)
	{
		emsg = strncpy(emsg, filename1, PATH_MAX);
		emsg = strncat(emsg, " existiert nicht!", 17);
		emsg = strncat("File ", emsg, (PATH_MAX + 17));
		BailOut(emsg);
	}

	/* open second file */
	if ((file2 = fopen(filename2, "r")) == NULL)
	{
		emsg = strncpy(emsg, filename2, PATH_MAX);
		emsg = strncat(emsg, " existiert nicht!", 17);
		emsg = strncat("File ", emsg, (PAH_MAX + 17));
		printf("%s\n", emsg);
				
		BailOut(emsg);
	}
}

die filenames kommen vom user (argumente beim programmaufruf), und werden ansich bereits bevor sie übergeben werden geprüft ob sie eh nicht länger als path_max sind.

wenn jetzt ein filename nicht existiert, bastel ich mir eine errormessage mit dem filename, die ich an BailOut() übergeben (das gibt die message aus, gibt resourcen wieder frei und terminiert das programm mit exitcode 1).
soweit sogut, aber spätestens nach dem 2. "strncat" führt jeder zugriff auf emsg zu einem "Bus error". (im 2. block hab ich ein printf() stehen um zu zeigen, dass es NICHT am BailOut() liegt).

zuerst dachte ich, es liegt am zu großen 3. parameter für strncat(), aber selbst wenn ich den beim 2. mal nur auf 1 setze kommt im anschluss der bus error.

angenommen einer der filenames ist "bloedsinn.txt" (und das file gibt es nicht).
dann liefert ein printf("%s\n", emsg) nach dem 1. strncat wie erwartet
"bloedsinn.txt existiert nicht!"

nach dem 2. strncat würde der gleiche aufruf eben den Bus Error verursachen.

das ganze kompiliert mit
gcc -ansi -pedantic -Wall -c
ohne warnings

weiß nur noch nicht sicher, ob es nicht ein plattformabhängiges problem ist.
(powerpc-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5250))

mach ich vielleicht irgend einen ganz schlimmen newbie-fehler? oder liegt es nicht an mir?


wäre für jede hilfe dankbar (auch für alternativen wie man das zusammenstöpseln der messages eleganter lösen kann).
Bearbeitet von Mr. Zet am 10.11.2007, 01:26

Nico

former person of interest
Registered: Sep 2006
Location: -
Posts: 4082
da fehlt ein T im PAH_MAX :)

that

Moderator
Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11338
Reiner Zufall, wenn das irgendwann funktioniert ... du schreibst über einen uninitialisierten Pointer an eine zufällige Speicheradresse.

Normalerweise macht man das ca. so:

Code:
char emsg[MAX_MSG_LEN];
snprintf(emsg, sizeof(emsg), "file %s existiert nicht", filename);
...

Mr. Zet

Super Moderator
resident spacenerd
Avatar
Registered: Oct 2000
Location: Edge of Tomorrow
Posts: 12040
*autsch*
Nicht initialisierter Pointer tut natürlich weh...
Muss zugeben ich bin was Pointer betrifft noch ziemlich unsicher, vor allem bei der Argumentübergabe und so. Beim Ausmerzen der Compilerfehler hab ich die Initialisierung dann ganz weg lassen, weil ich eine Meldung falsch interpretiert hab.

Also doch ein Newbiefehler :D

Danke that!

PS: snprintf ist geil, genau das hab ich gebraucht, kann ich den strncat crap rausschmeißen.
Hast du irgend eine GUTE Dokumentation der Standardlibraries bei der Hand?
manpages sind nicht wirklich hilfreich, wenn man eine gewisse Funktionalität sucht, aber keine Ahnung hat, ob es sowas gibt und wie die Funktion heißt.

Ich hab bisher auf
http://www.cppreference.com/all_c_functions.html
nachgeschlagen, aber da ist snprintf() nicht gelistet.

Am liebsten wäre mir etwas wie die Java API-Doc.

that

Moderator
Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11338

semteX

begehrt die rostschaufel
Avatar
Registered: Oct 2002
Location: Pre
Posts: 14592
dachte die stringfunktionen in c allokiern selbstständig den notwendigen speicher für die operation? muss ich wohl falsch in erinnerung gehabt haben... und def. gut zu wissen

mat

Administrator
Legends never die
Avatar
Registered: Aug 2003
Location: nö
Posts: 25422
Zitat von semteX
dachte die stringfunktionen in c allokiern selbstständig den notwendigen speicher für die operation? muss ich wohl falsch in erinnerung gehabt haben... und def. gut zu wissen
es gibt welche die es machen, a la strdup().. im großen und ganzen aber nicht => auf alle fälle in die dokumentation schauen.

Vivo

Dreamworker
Avatar
Registered: May 2002
Location: Tal der Könige
Posts: 1478
Zitat von Mr. Zet
Ich hab bisher auf
http://www.cppreference.com/all_c_functions.html
nachgeschlagen, aber da ist snprintf() nicht gelistet.
Weil snprintf soweit ich weiß nicht ANSI C ist ....

Mr. Zet

Super Moderator
resident spacenerd
Avatar
Registered: Oct 2000
Location: Edge of Tomorrow
Posts: 12040
Ist in ISO C99 und laut Wikipedia:
Zitat
C99

In March 2000, ANSI adopted the ISO/IEC 9899:1999 standard. This standard is commonly referred to as C99, and it is the current standard for C programming language.
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz