![]() |
[C] Funktion returned obwohl void!
void *nget(struct names *names, const char *name)
{ while (names) { if (strcmp(name,names->name) == 0) return names->value; else names = names->next; } return 0; } Wie ist das möglich??? Habe diesen Code ausschnitt von airstrike, Datei: names.c lg Etienne |
Wäre halt noch ganz brauchbar den Rest des - relevanten - Codes zu sehen und den verwendeten Compiler zu wissen
pong |
da es ein unter Linux laufendes Programm ist, verwendet es den g++ compiler.
#include <string.h> #include <malloc.h> #include <assert.h> #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include "names.h" /*Funktionsnamespace zum Ordnen von Strings, bzw chars! *Struktur für Namen, enthält, den Namen, eine Zahl, und ein Pointer *nächsten namen! */ struct names { char *name; void *value; struct names *next; }; //Number Get, liefert einen Zeigen auf die Struktur zurück (über esten Parameter), void *nget(struct names *names, const char *name) { while (names) { //Array mit names Strukturen durch gehen, //wenn names ungleich names if (strcmp(name,names->name) == 0) //Wenn return names->value; else names = names->next; } /* For the moment we fail here to catch bugs */ /*fprintf(stderr,"nget(): Did not find '%s'\n",name);*/ return 0; } int nhas(struct names *names, const char *name) { while (names) { if (strcmp(name,names->name) == 0) return 1; else names = names->next; } return 0; } void ndef(struct names **names, const char *name, void *value) { struct names *n = malloc(sizeof(*n)); n->next = *names; n->value = value; n->name = malloc(strlen(name) + 1); strcpy(n->name,name); *names = n; } void nundef(struct names **names, const char *name) { struct names *n; while (*names) { if (strcmp(name,(*names)->name) == 0) { n = *names; *names = (*names)->next; free(n->name); free(n); return; } else { names = &((*names)->next); } } } void nmap(struct names *names, void (*fn)(const char *name, void *value)) { while (names) { fn(names->name,names->value); names = names->next; } } void nfree(struct names **names) { struct names *n; while (*names) { n = *names; *names = (*names)->next; free(n->name); free(n); } } void nwrite_str(struct names *names, FILE *target) { while (names) { fprintf(target,"\"%s\" \"%s\"\n",names->name,(char *)names->value); names = names->next; } } static void skip_ws(FILE *f) { int c; while (isspace(c = fgetc(f)) && (c != EOF)) {} ungetc(c,f); } /* * Skips #..., whitespace and respects double quotes * Returns NULL at EOF or error */ static char *next_token(FILE *f) { int c; static char token[256]; char *s; again: skip_ws(f); c = fgetc(f); ungetc(c,f); if (c == '"') { if (fscanf(f,"\"%[^\"\n]\"",token) != 1) return 0; } else if (c == '#') { if (fscanf(f,"%*[^\n]") != 0) return 0; goto again; } else { if (fscanf(f,"%[^# \n\t={}]",token) != 1) return 0; } s = malloc(strlen(token) + 1); strcpy(s,token); return s; } void nread_str(struct names **names, FILE *target) { char *name,*value; while ((name = next_token(target))) { value = next_token(target); if (!value) { fprintf(stderr,"nread(): Invalid input at end of file.\n"); return; } ndef(names,name,value); free(name); } } lg Etienne |
hi,
was ist daran ungewöhnlich? die funktion ist so deklariert, dass sie einen void pointer zurückliefern kann und genau das macht sie. beachte: void pointer != void es wird hier also einfach ein untypisierter zeiger retour gegeben - etwas "gefährlich", außer man weiß, was man macht. der fall "return 0" ist - zugegebenerweise etwas ungewöhnlich, aber durchaus möglich - es wird eine referenz auf die speicherstelle an adresse 0 retour geliefert. und genau hier wirds problematisch - der aufrufende der funktion erhält zugriff auf den speicher an stelle 0 und kann dort irgendwas reinschreiben - und das führt dann wohl früher oder später zum programmabsturz - einer sog. "memory access violation" eine typsichere programmiersprache wie z.B. C# würde soetwas nicht erlauben und bereits beim kompilieren einen fehler melden. fg -hannes |
Zitat:
Code:
$> grep NULL /usr/include/linux/stddef.hCode:
return NULL;Code:
return 0;edit: ad typsichere sprachen. die speicheradresse 0 ist vom typ her eine gueltige adresse. der compiler schreit deswegen nicht. |
hi,
stimmt, es ist nicht ungewöhnlich NULL zurückzugeben - man schreibt dann für gewöhnlich aber auch NULL hin, nicht 0. Die tatsache, dass 0 durch NULL ersetzt wird (durch das define) erklärt eigentlich eh schon alles. ad typsichere sprachen: C#: unsafe void* fu1() { return 0; } Compilererror: error CS0266: Cannot implicitly convert type 'int' to 'void*'. An explicit conversion exists (are you missing a cast?) hingegen: unsafe void* fu1() { return null; } ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ========== fg -hannes |
danke wieder was gelernt!
lg Etienne |
| Alle Zeitangaben in WEZ +2. Es ist jetzt 15:38 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
© 2009 FSL Verlag