DEBIAN11 fdopen/popen Problem

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
kginbg
Beiträge: 2
Registriert: 08.03.2023 20:34:38

DEBIAN11 fdopen/popen Problem

Beitrag von kginbg » 09.03.2023 18:22:54

Ich verwende seit langer Zeit einen Textformatierer der auf DEBIAN8 fehlerfrei kompiliert und arbeitet. Nach Portierung auf DEBIAN11 erzeugt das Programm einen segfault. Der code enthaelt einen Aufruf von fdopen der beim kompilieren zu folgenden Warnmeldungen fuehrt:

Code: Alles auswählen

gcc test.c -std=c99 -L/home/klemens/progc/llib -L/lib -I/usr/include -I/usr/include/mysql -I/home/klemens/progc/include -lncurses -lown  -lm  -g -o test
test.c: In function 'main':
test.c:62:17: warning: implicit declaration of function 'fdopen'; did you mean 'fopen'? [-Wimplicit-function-declaration]
   62 |   if((outfile = fdopen(fd[1], "w")) == NULL)
      |                 ^~~~~~
      |                 fopen
test.c:62:15: warning: assignment to 'FILE *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
   62 |   if((outfile = fdopen(fd[1], "w")) == NULL)
      |               ^i
Headerfiles: #include <sys/types.h> #include <stdio.h>#include <stdlib.h> #include <unistd.h> #include <errno.h>

Um das Problem zu umgehen habe ich eine Loesung mit popen versucht
(wie TLPI S.902ff), die ebenfalls Warnngen verursacht:

Code: Alles auswählen

gcc test.c -std=c99 -L/home/klemens/progc/llib -L/lib -I/usr/include -I/usr/include/mysql -I/home/klemens/progc/include -lncurses -lown  -lm  -g -o test
test.c: In function 'main':
test.c:25:12: warning: implicit declaration of function 'popen'; did you mean 'fopen'? [-Wimplicit-function-declaration]
   25 |  outfile = popen (pcmd, "w");
      |            ^~~~~
      |            fopen
test.c:25:10: warning: assignment to 'FILE *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
   25 |  outfile = popen (pcmd, "w");
      |          ^
und bei Ausfuehrung ebenfalls zu einem segfault fuehrt.

Was mache ich hier falsch? vielen Dank fuer Hinweise im voraus.

kginbg.
Zuletzt geändert von JTH am 09.03.2023 23:20:20, insgesamt 2-mal geändert.
Grund: [code] eingefügt

JTH
Moderator
Beiträge: 3023
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: DEBIAN11 fdopen/popen Problem

Beitrag von JTH » 09.03.2023 19:32:26

Moin und willkommen im Forum.

Generell ists bei solchen Fragen sinnvoll (und meist ohne gar nicht zu beantworten), ein minimales Codebeispiel mitzuposten.

kginbg hat geschrieben: ↑ zum Beitrag ↑
09.03.2023 18:22:54

Code: Alles auswählen

test.c:62:17: warning: implicit declaration of function 'fdopen'; did you mean 'fopen'? [-Wimplicit-function-declaration]
Der Grund für die erste Warnung ist, dass du stdio.h nicht inkludiert hast. Dort sind fdopen und fopen deklariert, siehe https://manpages.debian.org/fdopen.3

Für eine nicht deklarierte Funktion wird der Rückgabetyp int angenommen. Daher folgt aus der ersten direkt die zweite Warnung.

Ich würd aus dem Stand allerdings sagen, dass das nicht die Ursache für deinen Segfault ist, schließlich sind es nur Warnungen. Möglicherweise hast du aber verwandte Folgefehler. Das zu beantworten geht allerdings nur mit dem dahintersteckenden Code, zumindest einem Auszug davon.
Manchmal bekannt als Just (another) Terminal Hacker.

Benutzeravatar
MSfree
Beiträge: 10773
Registriert: 25.09.2007 19:59:30

Re: DEBIAN11 fdopen/popen Problem

Beitrag von MSfree » 09.03.2023 19:43:10

JTH hat geschrieben: ↑ zum Beitrag ↑
09.03.2023 19:32:26
Für eine nicht deklarierte Funktion wird der Rückgabetyp int angenommen. Daher folgt aus der ersten direkt die zweite Warnung.

Ich würd aus dem Stand allerdings sagen, dass das nicht die Ursache für deinen Segfault ist
f(d)open liefern einen Zeiger zurück, der heutzutage 64 Bit lang ist. Int ist aber nur 32 Bit lang. Da kann ggfls zu einem Pufferüberlauf führen mit dazugehörigem Segfault.

Es wäre aber interessant, was für ein Formatierer das ist. Es gibt da draussen so viele, möglicherweise sogar im Debian Repository.

JTH
Moderator
Beiträge: 3023
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: DEBIAN11 fdopen/popen Problem

Beitrag von JTH » 09.03.2023 19:48:39

MSfree hat geschrieben: ↑ zum Beitrag ↑
09.03.2023 19:43:10
f(d)open liefern einen Zeiger zurück, der heutzutage 64 Bit lang ist. Int ist aber nur 32 Bit lang. Da kann ggfls zu einem Pufferüberlauf führen mit dazugehörigem Segfault.
Hast recht. Damit werden bei Zuweisung die oberen 32 Bit des 64-Bit-Pointers abgeschnitten. Das ist natürlich ein Grund für einen Speicherzugriff an der falschen Stelle.
Manchmal bekannt als Just (another) Terminal Hacker.

kginbg
Beiträge: 2
Registriert: 08.03.2023 20:34:38

Re: DEBIAN11 fdopen/popen Problem

Beitrag von kginbg » 09.03.2023 22:43:36

stdio.h ist included, wie geschrieben. Das ist es ja, was mich irritiert. Der Prototype von popen wird jedoch scheinbar nur includiert, wenn __USE_POSIX2 true ist. Habe ich versucht vor allen includes zu setzen, ohne Erfolg.

32 vs 64 Bit verstehe ich nicht, da mein Debian8 ebenfalls 64 Bit ist

Der Formatierer ist ein Eigenbau durch den ich alle meine Texte route. Die Problemstelle habe ich in ein kleines Template ausgelagert, nur Main und den Code aus TLPI S.929. Kann ich gerne Posten wenn's hilft. gdb stolpert bei dem popen Aufruf. Ich bin ratlos.
kgnbg.

Benutzeravatar
MSfree
Beiträge: 10773
Registriert: 25.09.2007 19:59:30

Re: DEBIAN11 fdopen/popen Problem

Beitrag von MSfree » 10.03.2023 08:39:03

kginbg hat geschrieben: ↑ zum Beitrag ↑
09.03.2023 22:43:36
32 vs 64 Bit verstehe ich nicht, da mein Debian8 ebenfalls 64 Bit ist
Die Prototypen für f(d)open sollten eigentlich so aussehen:

Code: Alles auswählen

FILE *fopen(const char *filename, const char *mode);
FILE *fdopen(int fd, const char *mode);
Fehlt der Prototyp, wird int also Rückgabewert von f(d)open vom Compiler angenommen.

Der Datentyp int ist aber nur 32 Bit lang, auch in einem 64 Bit System. Wer 64 Bit int verwenden will, muß sie als long long int deklarieren.

Der Datentyp FILE * ist, wie das Sternchen andeutet, ein Zeiger auf eine Speicheradresse, und Zeiger sind in einem 64 Bit Linux nunmal immer 64 Bit lang.

Bei der Wandlung des vermeintlich zurückgegebenen 32 Bit ints in den 64 Bit Zeiger gehen 4 Bytes verloren, so daß der Zeiger anschließend ins Siliziumnirvana zeigt, was einen Segfault zur Folge hat.

Antworten