[C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Wraith
Beiträge: 40
Registriert: 20.05.2006 20:18:23

[C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von Wraith » 29.04.2014 01:23:29

Hi,

irgendwo hier im Forum kann ich mich an ein Zitat erinnern, das da lautete: "Speicherallocation unter C ist boese."
Sagen wir: Es war interessant. :roll:

Wie auch immer. Folgendes: Ich moechte abhaengig von "meinen" Optionen verschiedene Optionen von einem externen Programm - hier GPG - aufrufen. Dazu folgende Umsetzung (Anm.: Uebersichtshalber habe ich die Positionen vertauscht, "TGfct_ramalloc" kommt zuerst.):

Code: Alles auswählen

[...]
        system(strcat(TGfct_ramalloc("--list-public-key "), TGvar_keyid));
[...]
Ich glaube, das versteht sich von selbst. "TGvar_keyid" ist das Argument, welches mit der Option "xyz" aus meinem Programm gesetzt wird. Mit der nachfolgenden Funktion "gestalte" ich den vollstaendigen GPG-Aufruf:

Code: Alles auswählen

char
*TGfct_ramalloc(char *TGfv_gpgopt)
{
    /* Within variables:
     *    TGfv_gpgopt     Given options for GPG
     *    TGfv_gpgbin     GPG binary include options
     *
     */
    char *TGfv_gpgbin;

    if (TGfv_gpgbin != NULL)
    {
        free(TGfv_gpgbin = NULL);
    }

    TGfv_gpgbin = (char *)malloc(5);
    strcpy(TGfv_gpgbin, "gpg ");
    TGfv_gpgbin = (char *)realloc(TGfv_gpgbin, strlen(TGfv_gpgopt) + 1);
    TGfv_gpgbin = strcat(TGfv_gpgbin, TGfv_gpgopt);
}
Soweit funktioniert das Ganze - es sei denn es gibt elegantere Loesungen.

Was mich allerdings ein wenig stoert, sind die beiden Schoenheitsfehler beim Compiler:

Code: Alles auswählen

gcc -Wall -o "abc" "abc.c" (in directory: ./src)
abc.c: In function ‘TGfct_ramalloc’:
abc.c:123:1: warning: control reaches end of non-void function [-Wreturn-type]
abc.c:123:8: warning: ‘TGfv_gpgbin’ is used uninitialized in this function [-Wuninitialized]
Compilation finished successfully.
Gibt es irgendwie die Moeglichkeit "sauber" aus der Funktion zu kommen?

Code: Alles auswählen

return(0);
faellt flach. :|

gtz
- Wraith

brummer
Beiträge: 181
Registriert: 19.02.2007 19:21:23

Re: [C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von brummer » 29.04.2014 06:29:55

Jetzt ma nur so aus dem Stegreif, wenn du keinen char zurückgeben willst, kannst du void nehmen.
und TGfv_gpgbin kannst du mit NULL initialisieren. Damit sollten die Warnungen verschwinden.
char *TGfv_gpgbin = NULL;

Ich verstehe allerdings nicht was diese Funktion soll, da hier TGfv_gpgbin ja nur eine locale variable in der Funktion ist, die außerhalb nicht mehr zu erreichen ist. Sieht mir schwer nach einem mem-leak aus . :)

Benutzeravatar
schorsch_76
Beiträge: 2535
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: [C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von schorsch_76 » 29.04.2014 07:27:10

Das am Ende kein return steht, ist das eine. Gib entweder NULL zurück oder ändere die Funktionsdeklaration und Implementierung dieser Funktion (void anstatt char*).

Code: Alles auswählen

char *TGfv_gpgbin;

    if (TGfv_gpgbin != NULL)
das ist ja wohl klar, das hier der Compiler meckert, dass gpgbin nicht initialisiert verwendet wird. Woher soll denn der Wert kommen? Wolltest du hier eine andere Variable abfragen?

Benutzeravatar
Wraith
Beiträge: 40
Registriert: 20.05.2006 20:18:23

Re: [C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von Wraith » 29.04.2014 07:44:39

schorsch_76 hat geschrieben:[...] Wolltest du hier eine andere Variable abfragen?
Ne, ich habe ein grundaetzliches Verstaendnisproblem, was Variablen unter C angehen.
Variablen sind fuer mich halt temporaer. Das diese - jetzt mal von "static", "extern" usw. abgesehen - beim Verlassen der Funktionen floeten gehen, ist mir klar. Speicher hingegen ist fuer mich nicht temporaer.

Ich bin davon ausgegangen (Grob)...: Reserviere ich Speicher innerhalb der Funktion, ist dieser auch weiterhin reserviert und behaelt damit seinen Inhalt. Mit der Abfrage (if (TGfv_gpgbin != NULL)) sollte eigentlich nur geprueft werden, ob die alte Befehlszeile noch im Speicher ist, um sie anschliessend mit "free" wieder freizugeben - da dann eine neue Befehlszeile erstellt wird.

Hintergrund dieser Funktion war eigentlich nur, dass ich die Befehlszeile fuer GPG staendig anpassen muss und mir mit dieser Funktion das staendige realloc und free ersparen wollte.

gtz
- Wraith

Benutzeravatar
schorsch_76
Beiträge: 2535
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: [C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von schorsch_76 » 29.04.2014 08:52:01

Diese lokale Variable hat zwar den gleichen namen wie die Variable, die irgendwo verwendet wird, sie ist aber sonst nichts mit ihr gemeinsam. Willst du die gleiche Variable abfragen, mach sie global, oder übergib sie als Paramater.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: [C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von Cae » 29.04.2014 08:52:57

Wraith hat geschrieben:Ich bin davon ausgegangen (Grob)...: Reserviere ich Speicher innerhalb der Funktion, ist dieser auch weiterhin reserviert und behaelt damit seinen Inhalt.
Soweit stimmt das. Aber wenn du keinen Pointer auf diesen Speicher hast, bringt er dir nichts (bzw. das ist dann ein Speicherleck, memory leak, weil du fuer dieselben Daten immer wieder neuen Speicher anfordern musst). Und der Pointer ist wegen dem Scoping weg. Ich habe den Eindruck, dass es so gedacht war (abgeaendert: KNF, kurze Variablen, kein Kommentarheader):

Code: Alles auswählen

char * addopt(char *bin, char *opt) {
	const char base[] = "gpg ";
	size_t baselen = strlen(base);
	size_t optlen = strlen(opt);

	/* malloc(a) == realloc(NULL, a) */
	bin = (char *)realloc(bin, baselen + optlen + 1);

	strncpy(bin, base, baselen);
	strncpy(bin + baselen, opt, optlen);

	return bin;
}

char *b = NULL;

b = addopt(b, "--version");
printf("%s\n", b);
b = addopt(b, "--list-secret-keys");
printf("%s\n", b);
Schoener waer's allerdings, einen Pointer auf einen Pointer zu uebergeben, der von der Funktion automatisch abgeaendert wird. Das b = addopt() unten vergisst man leicht zu addopt() und dann hat b entweder nach wie vor NULL (== segfault) oder halt den Vorgaengerwert (== schwierig zu entdeckender Bug).

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

wanne
Moderator
Beiträge: 7448
Registriert: 24.05.2010 12:39:42

Re: [C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von wanne » 29.04.2014 14:51:39

Was du eigenlich machen willst ist glaube ich das:

Code: Alles auswählen

char
*TGfct_ramalloc(char *TGfv_gpgopt)
{
    /* Within variables:
     *    TGfv_gpgopt     Given options for GPG
     *    TGfv_gpgbin     GPG binary include options
     *
     */
    static char *TGfv_gpgbin=NULL;

    if (TGfv_gpgbin != NULL)
    {
        free(TGfv_gpgbin)
        TGfv_gpgbin = NULL;
    }

    TGfv_gpgbin = (char *)malloc(5);
    strcpy(TGfv_gpgbin, "gpg ");
    TGfv_gpgbin = (char *)realloc(TGfv_gpgbin, strlen(TGfv_gpgopt) + 1);
    TGfv_gpgbin = strcat(TGfv_gpgbin, TGfv_gpgopt);
    return TGfv_gpgbin;
}
Schön währe es aber eher so:

Code: Alles auswählen

char
*TGfct_ramalloc(char *TGfv_gpgopt)
{
    /* Within variables:
     *    TGfv_gpgopt     Given options for GPG
     *    TGfv_gpgbin     GPG binary include options
     *
     */
    size_t len=strlen(TGfv_gpgopt)+1;
    static char *TGfv_gpgbin=NULL;

    if(!TGfv_gpgbin)
    {
        TGfv_gpgbin=(char*)malloc(len + 4);
        strcpy(TGfv_gpgbin,"gpg ");
    }
    
    TGfv_gpgbin = (char *)realloc(TGfv_gpgbin, len + 4);
    return memcpy(TGfv_gpgbin+4,TGfv_gpgopt,len);
}
Oder mit jedes mal neu reinkopieren von "gpg "

Code: Alles auswählen

char
*TGfct_ramalloc(char *TGfv_gpgopt)
{
    /* Within variables:
     *    TGfv_gpgopt     Given options for GPG
     *    TGfv_gpgbin     GPG binary include options
     *
     */
    size_t len=strlen(TGfv_gpgopt)+1;
    static char *TGfv_gpgbin=NULL;
    
    TGfv_gpgbin = (char *)realloc(TGfv_gpgbin, len + 4);
    strcpy(TGfv_gpgbin,"gpg ");
    return memcpy(TGfv_gpgbin+4,TGfv_gpgopt,len);
}
rot: Moderator wanne spricht, default: User wanne spricht.

wanne
Moderator
Beiträge: 7448
Registriert: 24.05.2010 12:39:42

Re: [C] S:Meinung & evtl. Tipp fuers Compiler-Schweigen

Beitrag von wanne » 29.04.2014 19:55:42

Achso: Zum verständnis lies dir vielleicht mal den Unterschied zwichen Sichtbarkeit und Lebensdauer in der Wikipedia durch: https://de.wikipedia.org/wiki/Variable_(Programmierung)
Edit zur weiteren erklärung: Sichtbarkeiten werden in C durch den platz an der die Variablen definiert wurden bestimmt lebensdauern sind etwas komplexer: das geht für speicher mit malloc und free manuell. Oder mit alloca für die laufzeit der aktuellen Funktion, mit static für die ganze Laufzeit des Programms oder für lokale Variablen nur für die laufzeit des aktuellen Blocks. Anmerkung: Das sind alles nur mindestlebensdauern. Die laufzeitumgebung kann da auch länger leben lassen.
rot: Moderator wanne spricht, default: User wanne spricht.

Antworten