Segmentation fault bei fgets

centhron69

Grünschnabel
Programmiersprache: C
System: openBSD
Compiler: gcc
Debugger: gdb

Hi,

folgendes Problem:

Ich möchte aus einer seriellen Schnittstelle auslesen. Nun hab ich das kleine Programm in einer main geschrieben und getestet. Es hat funktioniert. Anschließend hab ich das Programm auf mehrere Dateien verteilt (main.c func.c func.h) und nun kommt bei fgets ein Segmentation Fault.

main.c
Code:
#include"func.h"

int main(void)
{
	const char *COM_IN_NAME = "/dev/cua00";		//input COM name
	const char *COM_OUT_NAME = "/dev/cua01";	//output COM name

	FILE* com_in;		//COM Inpu
	FILE* com_out;		//COM Output

	char str[100];		//Read-Write String
	//-------------------------------------------------------------------------------------------------
	
	read(COM_IN_NAME, str, com_in);
	
	return 0;
}

func.c
Code:
#include"func.h"

int read(const char *COM_IN_NAME, char *str, FILE *com_in)
{
	//input filestream oeffnen
	com_in = fopen(COM_IN_NAME, "r");
	if(com_in == NULL)	
	{
		printf("%s konnte nicht geoeffnet werden\n", COM_IN_NAME);
		return 1;
	}
	
	//lesen bis <ENTER> oder max-groeße erreicht
	fgets(str, 100, com_in);
	printf("%s",str);

	return 0;
}

int write(const char * COM_OUT_NAME, char *str, FILE *com_out)
{
	//output filestream oeffnen
	com_out = fopen(COM_OUT_NAME, "w");
	if(com_out == NULL)
	{
		printf("%s konnte nicht geoffnet werden\n", COM_OUT_NAME);
		return 1;
	}

	fputs(str, com_out);

	return 0;		
}

Wenn ich Zeile 14 auskommentier funktioniert das Programm

func.h
Code:
#include<stdio.h>

int read(const char *COM_IN_NAME, char* str, FILE* com_in);

int write(const char *COM_OUT_NAME, char* str, FILE* com_out);

Der Debugger ist leider auch nicht hilfreich. Er schreibt:

Code:
Program received singal SIGSEGV, Segmentation fault.
strlen (str=0x6 <Address 0x6 out of bounds>)
at /usr/src/lib/libc/string/strlen.c:43 
/usr/src/lib/libc/string/strlen.c: no such file or directory
in /usr/src/lib/libc/string/strlen.c:

Wobei ich strlen gar nicht benutze x__X. Kennt jemand den Fehler?

Viele Dank für die Hilfe :)
 
Hi.

1. gibt der Compiler Warnungen aus? (mit "-Wall" kompilieren!)
2. es gibt bereits ein Systemfunktionen namens read und write
3. kompiliere mit Debug-Informationen (-g)
4. drücke "bt full <ENTER>" im gdb und zeige die Ausgabe

Gruß
 
1.
main.c:15:35: Warnung: »com_in« wird in dieser Funktion uninitialisiert verwendet [-Wuninitialized]
main.c:16:38: Warnung: »com_out« wird in dieser Funktion uninitialisiert verwendet [-Wuninitialized]

Ich vermute mal, dass ich die Warnung ignorieren kann da ich diese in der Funktion initialisier.

2. Hab sie nun in readCom und writeCom umbenannt


Es hat funktioniert. Lag wohl doch nur am read/write Befehl. Sollte da nicht irgendwie ein Fehler kommen?

Viele Dank für die Hilfe :D. Mein Kopf hat schon wehgetan wegen dem ganzen grübeln.
 
1.
main.c:15:35: Warnung: »com_in« wird in dieser Funktion uninitialisiert verwendet [-Wuninitialized]
main.c:16:38: Warnung: »com_out« wird in dieser Funktion uninitialisiert verwendet [-Wuninitialized]

Ich vermute mal, dass ich die Warnung ignorieren kann da ich diese in der Funktion initialisier.
Du initialisierst diese in den Funktionen, ja. Aber das hat ja keine Auswirkung auf die lokalen Variablen in main.

Somit hast du ein Leck von Dateideskriptoren in den Funktionen readCom und writeCom.

Gruß
 
Was ist ein Leck im Dateideskriptor? Was kann passieren wenn ich einen hab?

Gibts dazu irgendwo infos? Find keine im Internet...
 
Hi

Du schließt dein com_in nicht (fopen braucht auch ein fclose...) und verlierst die Variable am Funktionsende. So, wie du das FILE* aus dem main übergibst, hast du das geöffnete FILE nach Funktionsende im main nicht mehr verfügbar.

Und da es anscheinend egal ist, welcher Wert am Funktionsanfang übergeben wird (es wird ja jedenfalls überschrieben), warum übergibst du dann überhaupt ein FILE* ?
 
Was ist ein Leck im Dateideskriptor?
Nicht im Dateideskriptor, sondern von Dateideskriptoren.

Zu jedem (erfolgreichen) fopen gehört ein fclose.
Was kann passieren wenn ich einen hab?
Du verbrauchst (limitierte) Resourcen. Wenn du das oft genug in deinem Programm machst, wird es abstürzen...
Gibts dazu irgendwo infos? Find keine im Internet...
http://encyclopedia2.thefreedictionary.com/file+descriptor+leak

Gruß
 
Du schließt dein com_in nicht (fopen braucht auch ein fclose...) und verlierst die Variable am Funktionsende.

Habs nun geschlossen.

So, wie du das FILE* aus dem main übergibst, hast du das geöffnete FILE nach Funktionsende im main nicht mehr verfügbar.

Und da es anscheinend egal ist, welcher Wert am Funktionsanfang übergeben wird (es wird ja jedenfalls überschrieben), warum übergibst du dann überhaupt ein FILE* ?

Stimmt. Macht überhaupt keinen Sinn :). Habs entfernt.

Danke nochmal an sheel und deepthroat.

Hier nochmal meine funktionierende Lösung:

main.c
Code:
#include"func.h"

int main(void)
{
	const char *COM_IN_NAME = "/dev/cua00";		//input COM name
	const char *COM_OUT_NAME = "/dev/cua01";	//output COM name

	char str[100];		//Read-Write String
	
	//-------------------------------------------------------------------------------------------------
	
	readCom(COM_IN_NAME, str);
	writeCom(COM_OUT_NAME, str);
	return 0;
}

func.c
Code:
#include"func.h"

int readCom(const char *COM_IN_NAME, char *str)
{
	//input filestream oeffnen
	FILE *com_in;
	com_in = fopen(COM_IN_NAME, "rb");
	if(com_in == NULL)	
	{
		printf("%s konnte nicht geoeffnet werden\n", COM_IN_NAME);
		return 1;
	}
	
	//lesen bis <ENTER> oder max-groeße erreicht
	fgets(str, 100, com_in);
	printf("%s",str);

	fclose(com_in);
	return 0;
}

int writeCom(const char *COM_OUT_NAME, char *str)
{
	//output filestream oeffnen
	FILE* com_out;
	com_out = fopen(COM_OUT_NAME, "wb");
	if(com_out == NULL)
	{
		printf("%s konnte nicht geoffnet werden\n", COM_OUT_NAME);
		return 1;
	}
	
	fputs(str, com_out);

	return 0;		
}

func.h
Code:
#include<stdio.h>

int readCom(const char *COM_IN_NAME, char* str);

int writeCom(const char *COM_OUT_NAME, char* str);
 
Zuletzt bearbeitet:
Zurück