# C - struct pointer in struct



## nero-15 (11. November 2008)

Hallo,
ich habe ein kleines Progrämmchen zu Laufzeittests geschrieben und habe ein Problem. Ich bekomme immer die Fehlermeldung Speicherzugriffsfehler. Beim kompilieren gibts keine Fehler. Die problematische Stelle das Codes sind die Zeilen 25 - 28, wo die Werte aus den Strukturen gelesen werden:


```
start_sec = t->start_ts->tv_sec;
start_usec = t->start_ts->tv_usec;
stop_sec = t->stop_ts->tv_sec;
stop_usec = t->stop_ts->tv_usec;
```

Hier der Quelltext:


```
#include <sys/time.h>
#include <stdio.h>

struct tstamp {
	struct timeval *start_ts;
	struct timeval *stop_ts;
};

struct timezone *tz;

// Setzt den Startpunkt für die Zeitmessung
void start(struct tstamp *t){
	gettimeofday(t->start_ts,tz);
}

// Setzt den Stoppunkt für die Zeitmessung
void stop(struct tstamp *t){
	gettimeofday(t->stop_ts,tz);
}

// Wertet Start und Stoppunkt zu einer Ausführungszeit aus
unsigned long extime(struct tstamp *t){
	int start_sec,start_usec,stop_sec,stop_usec,dif_usec,dif_sec;
	unsigned long ret_usec; // Rückgabewert in Mikrosekunden
	start_sec = t->start_ts->tv_sec;
	start_usec = t->start_ts->tv_usec;
	stop_sec = t->stop_ts->tv_sec;
	stop_usec = t->stop_ts->tv_usec;
	dif_sec = stop_sec - start_sec;
	dif_usec = stop_usec - start_usec;
	//Falls dif_usec negativ ist
	if(dif_usec < 0){
		dif_sec = dif_sec - 1;			// eine Sekunde abziehen
		ret_usec = 1000000 + dif_usec;	// Differenz in Mikrosekunden ermitteln
	}
	ret_usec = ret_usec + dif_sec * 1000000;
	return (ret_usec);
}

int main(void){
	int i;
	int a = 99;
	struct tstamp *ts;
	start(ts);
	// ein wenig Rechenzeit verbraten
	for(i = 0 ; i < 1000 ; i++){
		a = a*a*a*a*a*a;
	}
	stop(ts);
	printf("%lu\n",extime(ts));
}
```

Ich würde mich freuen, wenn mir jemand weiterhelfen könnte, da ich mit meinem Latein am Ende bin. Vielen Dank


----------



## Matthias Reitinger (12. November 2008)

nero-15 hat gesagt.:


> ```
> struct tstamp *ts;
> start(ts);
> ```


Du verwendest die Variable ts, ohne sie initialisiert zu haben.


----------



## nero-15 (12. November 2008)

Das kann nicht sein. Auch mit Initialisierung funktioniert es nicht. Das Problem müsste wie gesagt in dieser Anweisung liegen 

t->start_ts->tv_sec

Irgendwie löst er das nicht richtig auf. Ich habe jetzt schonwieder ewig viel ausprobiert und komme einfach auf keinen grünen Zweig.


----------



## deepthroat (12. November 2008)

nero-15 hat gesagt.:


> Das kann nicht sein. Auch mit Initialisierung funktioniert es nicht.


Was heißt das? Immer noch der gleiche Fehler? Wie sieht dein Code denn jetzt aus?

Gruß


----------



## jsendrow (12. November 2008)

nero-15 hat gesagt.:


> Das kann nicht sein. Auch mit Initialisierung funktioniert es nicht. Das Problem müsste wie gesagt in dieser Anweisung liegen
> 
> t->start_ts->tv_sec
> 
> Irgendwie löst er das nicht richtig auf. Ich habe jetzt schonwieder ewig viel ausprobiert und komme einfach auf keinen grünen Zweig.



Es IST aber so.

struct tstamp *ts;

Das ist ein ZEIGER vom Typ tstamp. Ein Zeiger zeigt auf einen Speicherbereich in dem das Objekt liegt. Dazu muss der Speicherbreich aber zuerst initialiert werden, was Du heir nicht machst. Zu diesem Zeitpunkt zeigt der Zeiger auf einen beliebigen Speicherbereich.

start(ts);

Hier übergibtst Du den immer noch nicht initialisierten Zeiger .

gettimeofday(ts->start_ts,tz);

Jetzt wird es listig. Du läßt die FUnktion in einen nicht initialisierten Speicher schreiben. Das Verhalten ist undefiniert. Da gettimeofday keinerlei Fehlermeldungen zurückgibt kann hier also schon so ziemlich alles schieflaufen ohne das Du es bemerkst.

start_sec = ts->start_ts->tv_sec;

hier knallt es dann endgültig weil Du jetzt auf einen Member einer nicht Initialisierten Struktur zugreifen willst. 


Fazit:

Entweder:

struct tstamp *ts = new struct tstamp; // Speicher auf dem Heap reservieren.

oder 

struct tstamp ts; // Speicher auf dem Stack belegen



PS:


nero-15 hat gesagt.:


> Das kann nicht sein.


Warum kommst Du und bittest um Hilfe wenn Du es dann ja doch besser weisst als die Leute hier.  Matthias Reitinger hatte vollkommen recht mit seiner Aussage.


----------

