Pointer on Pointer Problem

Vippis

Mitglied
Hallo,


Ich habe die Aufgabe eine Funktion zu schreiben die ein doublefeld der Länge x erzeugt, dafür Speicher reserviert und zu Beginn mit Nullen beschreibt. Die Funktionsargumente sind vorgegeben.

Code:
void allocMem(int length, void **ptrptr){
	
	
	
    *ptrptr =(void*)(malloc(length*sizeof(double))); 
	memset(ptrptr,0,length);    /* oder ?*/  memset(*ptrptr,0,length);

      
	
/* free wird in der main aufgerufen*/	
	
	
    
	
};

Erstmal. Der **ptrptr zeigt doch ohne weitere Zuweisung auf *ptrptr bzw. damit auch auf den Wert ptrptr. Mit Malloc erzeuge ich doch schon so etwas wie ein Feld. Kein Array, aber man könnte damit zB. auch ein Sortierverfahren(in Aufgaben teil b verlangt) durchführen.

Ich probiere jetzt schon 1,2 Stündchen an den paar Zeilen rum und komme nicht vorran. Es tritt immer irgendein Speicherfehler ein.
 
Hi.
Ich habe die Aufgabe eine Funktion zu schreiben die ein doublefeld der Länge x erzeugt, dafür Speicher reserviert und zu Beginn mit Nullen beschreibt. Die Funktionsargumente sind vorgegeben.
Code:
void allocMem(int length, void **ptrptr){
    *ptrptr =(void*)(malloc(length*sizeof(double))); 
	memset(ptrptr,0,length);    /* oder ?*/  memset(*ptrptr,0,length);	
};

Erstmal. Der **ptrptr zeigt doch ohne weitere Zuweisung auf *ptrptr bzw. damit auch auf den Wert ptrptr. Mit Malloc erzeuge ich doch schon so etwas wie ein Feld. Kein Array, aber man könnte damit zB. auch ein Sortierverfahren(in Aufgaben teil b verlangt) durchführen.
ptrptr ist ein Zeiger auf einen Zeiger; zeigt also auf eine andere Zeigervariable - bzw. anders ausgedrückt darin ist die Adresse einer Variablen gespeichert (die selbst wiederum ein Zeiger ist).

Du mußt innerhalb der Funktion lediglich den Wert der referenzierten Variable ändern bzw. auf diesen Zugreifen. (also immer *ptrptr verwenden)

Außerdem brauchst du nicht malloc und memset zu verwenden. Es gibt bereits eine Standardfunktion dafür: calloc.

\edit: falls du übrigens alle double Werte in dem Array auf 0.0 setzen möchtest, mußt du eine Schleife verwenden.

Und memset erwartet eine Größe in Bytes, d.h. du mußt wie bei malloc auch "length * sizeof(double)" angeben.

Gruß
 
Zuletzt bearbeitet:
Hallo,

In der Aufgabe ist leider gefordert es so zu machen. Also sowohl malloc als auch memset zu nutzen.

Ich frage mich auch, ob ich das falsch übergebe.

allocMem(laenge, *ptrptr);

Stimmt das so ?


Und wo liegt der Fehler in der Funktion. Ich nutze doch nur *ptrptr in der Funktion selber.
 
Hallo,

In der Aufgabe ist leider gefordert es so zu machen. Also sowohl malloc als auch memset zu nutzen.

Ich frage mich auch, ob ich das falsch übergebe.

allocMem(laenge, *ptrptr);

Stimmt das so ?
Wie ist ptrptr deklariert? Was sagt denn dein Compiler dazu? (Warnungen?) ;-]
Und wo liegt der Fehler in der Funktion. Ich nutze doch nur *ptrptr in der Funktion selber.
Nein, du hast dort memset(ptrptr, ...) geschrieben. Die 2. Variante ist richtig. Beachte auch mein Edit in meiner ersten Antwort.

Gruß
 
So sieht die main dazu aus. Der Compiler meckert gar nicht. Nur der Debugger sagt mir das es in der malloc Zeile einen Bad Access gibt (viel mehr jedoch nicht).

Code:
int main () {

	
	
	void **ptrptr;
	int laenge=10;
	
	
 	allocMem(laenge, *ptrptr); 
	
	free(*ptrptr);
    return 0;
	
}

Zu memset:

memset beschreibt also nur ein Array teil. Muss ich das über eine forschleife erst initialiesieren ?
So zB. ?

Code:
for(k=0;k<length;k++){
	memset(ptrptr[k],0.0,length*sizeof(double));
	}
 
Zuletzt bearbeitet:
So sieht die main dazu aus. Der Compiler meckert gar nicht.
Welchen Compiler verwendest du? Hast du auch alle Warnungen angeschaltet?

Mein Compiler sagt dazu:
Code:
memf.c:8:22: warning: 'ptrptr' is used uninitialized in this function
Du derenferenziert beim Aufruf der allocMem Funktion einen Zeiger der überhaupt nirgends hinzeigt (du hast ihn nicht initialisiert).

Du mußt der Funktion schon einen Zeiger auf eine existierende Variable (also deren Adresse) übergeben.
C:
int main(void) {
  void *ptr;
  int laenge = 10;

  allocMem(laenge, &ptr);
  ...
}
Zu memset:

memset beschreibt also nur ein Array teil. Muss ich das über eine forschleife erst initialiesieren ?
Man kann einfach (portabel) mit memset kein double Array mit 0.0 initialisieren. memset schreibt nur die angegebenen Bytes in den Speicher. Ein double ist (in der Regel) 8 Bytes groß. Es ist nicht festgelegt, das 8 aufeinderfolgende binäre Nullen dem double-Wert 0.0 entsprechen.

Gruß
 
Mmhh... total verwirrt.^^

Wenn ich das richtig verstehe. Ich brauche ein Array (double?) in der main auf das der pointer zeigen kann?


Ich nutze Xcode auf Mac OS(damit ich auch inner Uni was programmieren kann) Soweit ich weiß nutzt das den gcc Compiler.
 
Wenn ich das richtig verstehe. Ich brauche ein Array (double?) in der main auf das der pointer zeigen kann?
Nein, du brauchst kein Array in main. Du brauchst eine Variable. Die Adresse dieser Variablen übergibst du an die Funktion, damit die Funktion den Wert der Variablen direkt ändern kann. Die Funktion erzeugt dann das Array.
Ich nutze Xcode auf Mac OS(damit ich auch inner Uni was programmieren kann) Soweit ich weiß nutzt das den gcc Compiler.
Dann schalte die Warnungen an (Compiler Option -Wall).

Gruß
 
Ich muss sagen ich stehe ganz schön auf dem Schlauch. Gott sei Dank hat man als Etechniker nur ein Semester Informatik.^^

Code:
        void **ptrptr;
	
	int laenge=10;
	double feld;
	*ptrptr = &feld;
	
	
 	allocMem(laenge, *ptrptr);

So geht das ja scheinbar nicht. In deinem Beispiel war es ja nur ein einfacher Pointer. Aber normalerweise müsste das doch so funktionieren. **ptrptr zeigt auf *ptrptr und der wiederum zeigt auf einen Wert. Anschließend wird die Adresse (also *ptrptr) des Zweifachen pointers übergeben.
 
Ich muss sagen ich stehe ganz schön auf dem Schlauch. Gott sei Dank hat man als Etechniker nur ein Semester Informatik.^^

Code:
        void **ptrptr;
	
	int laenge=10;
	double feld;
	*ptrptr = &feld;
	
	
 	allocMem(laenge, *ptrptr);

So geht das ja scheinbar nicht. In deinem Beispiel war es ja nur ein einfacher Pointer. Aber normalerweise müsste das doch so funktionieren.
Nein, tut es nicht.
**ptrptr zeigt auf *ptrptr
Nein. (**ptrptr) zeigt grundsätzlich nirgendwo hin. (**ptrptr) ist ein void.

Die Variable ptrptr ist ein (void**) und könnte auf ein (void*) zeigen, dazu müßte man die Variable allerdings erstmal initialisieren.

Du hast die Variable immer noch nicht initialisiert. Und dennoch hast du die Variable schon wieder de-referernziert (Zeile 5) => Speicherzugriffsfehler.

Schalte die Warnungen des Compilers ein:
Code:
memf.c:9:13: warning: 'ptrptr' is used uninitialized in this function
Eine void** Variable in der main Funktion zu benutzen ist unsinnig.

Weiterhin hast du versucht eine double Variable als Feld zu missbrauchen...

C:
void* ptr; // zeigt nirgendwo hin
void** ptrptr;  // zeigt nirgendwo hin

ptrptr = &ptr; // ptrptr zeigt auf ptr

int x = 5;

*ptrptr = &x; // (*ptrptr) == ptr == &x -- ptr zeigt auf x, ptrptr zeigt auf ptr

Gruß
 
Zuletzt bearbeitet:
Zurück