WCM - Das österreichische Computer Magazin Forenübersicht
 

Zurück   WCM Forum > Rat & Tat > Programmierung

Programmierung Rat & Tat für Programmierer

Microsoft KARRIERECAMPUS

Antwort
 
Themen-Optionen Ansicht
Alt 25.09.2005, 18:54   #1
Etienne
Veteran
 
Registriert seit: 31.03.2003
Alter: 37
Beiträge: 403


Etienne eine Nachricht über ICQ schicken
Standard [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
Etienne ist offline   Mit Zitat antworten
Alt 25.09.2005, 20:00   #2
pong
Inventar
 
Benutzerbild von pong
 
Registriert seit: 25.12.2000
Alter: 41
Beiträge: 9.063

Mein Computer

pong eine Nachricht über ICQ schicken
Standard

Wäre halt noch ganz brauchbar den Rest des - relevanten - Codes zu sehen und den verwendeten Compiler zu wissen

pong
____________________________________
\"Ein Gewitter reinigt die Luft\", sagte der Mann, nachdem ein Blitz seine Frau erschlug

Nicht klicken!


Erstposteralarm/Beschwerde/Kummerkasten


Verplattet
pong ist offline   Mit Zitat antworten
Alt 25.09.2005, 20:53   #3
Etienne
Veteran
 
Registriert seit: 31.03.2003
Alter: 37
Beiträge: 403


Etienne eine Nachricht über ICQ schicken
Standard

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
Etienne ist offline   Mit Zitat antworten
Alt 25.09.2005, 21:22   #4
Biri
Hero
 
Registriert seit: 04.09.2001
Beiträge: 894


Standard

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
Biri ist offline   Mit Zitat antworten
Alt 26.09.2005, 09:42   #5
Who-T
Elite
 
Registriert seit: 01.08.2000
Beiträge: 1.395


Who-T eine Nachricht über ICQ schicken
Standard

Zitat:
Original geschrieben von Biri

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.
Code:
$> grep NULL /usr/include/linux/stddef.h
#undef NULL
#define NULL 0
#define NULL ((void *)0)
Es ist nicht ungewoehnlich NULL zurueckzugeben. dies ist bei den meisten bibliotheken der standard. NULL ist (wie der name schon sagt) definiert auf 0.

Code:
return NULL;
ist also das gleiche wie
Code:
return 0;
wobei ich persoenlich erstes bevorzuge.


edit:
ad typsichere sprachen. die speicheradresse 0 ist vom typ her eine gueltige adresse. der compiler schreit deswegen nicht.
____________________________________
Whoever built humanity left in a major design flaw: it was the tendency to bend at the knees.
Who-T ist offline   Mit Zitat antworten
Alt 26.09.2005, 10:00   #6
Biri
Hero
 
Registriert seit: 04.09.2001
Beiträge: 894


Standard

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
Biri ist offline   Mit Zitat antworten
Alt 27.09.2005, 16:11   #7
Etienne
Veteran
 
Registriert seit: 31.03.2003
Alter: 37
Beiträge: 403


Etienne eine Nachricht über ICQ schicken
Standard

danke wieder was gelernt!

lg Etienne
Etienne ist offline   Mit Zitat antworten
Antwort


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.

Gehe zu


Alle Zeitangaben in WEZ +2. Es ist jetzt 19:47 Uhr.


Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Forum SEO by Zoints
© 2009 FSL Verlag