2009-08-05 17 views
0

Ich möchte einfach übergeben ein char als Argument an eine Funktion , die dann von der Funktion geändert werden sollte. Leider, wenn Sie es wie unten tun, sind die Ausdrucke der Puffer NICHT gleich. Ich verstehe nicht, wie ich einen Zeiger auf die Char-Array übergeben. Jeder sieht die offensichtliche Sache , die fehlt?C++: einfaches passing char *?

unsigned char* buffer; 
doSomething(buffer) 
printout(buffer); 

wo doSomething() ist definiert als:

doSomething(unsigned char *buffer) 
{ 
    char* receiveddata; 
    Socket.recv(receiveddata); 
    buffer = (unsigned char*) receiveddata; 
    printout(buffer); 
} 
+0

Warum ist das mit "C++" markiert? Es ist reiner C-Code. Und es enthält eine Reihe von Fehlern, die C++ verhindern soll. – sbi

+0

Nein, ist es nicht. Er ruft die recv() - Methode eines Objekts namens Socket auf. Das kannst du nicht in C machen. –

+2

@Neil: Du hast sicherlich Recht, ich habe übersehen, dass dieser Aufruf C++ ist. Aber warum sollte reines C um diesen Aufruf geschrieben werden, wodurch das Ressourcenmanagement so durcheinander gebracht wird, dass das OP eher eine Sprache verwenden sollte, die kein manuelles Ressourcenmanagement erfordert? – sbi

Antwort

0

ich Sie erraten müssen einige Speicher auf receivedData zuzuteilen, nicht nur den Zeiger.

Sieht so aus, als ob Socket.recv (receiveddata) die empfangenen Daten in diesen Zeiger kopieren soll, aber der Zeiger auf ungültigen Speicher zeigt. Versuch:

receiveddata = malloc(10000); 

Vor socket.recv (receivedData)

2

Ich weiß nicht, was Bibliotheken Sie für Steckdosen verwendet. Aber ich nehme an, dass Sie zuerst den Puffer reservieren müssen, um Daten zu erhalten. Nur Empfangsdaten zu deklarieren, ohne Zuweisung (nicht einmal Initialisierung) führt zu undefiniertem Verhalten.

Nur Raten.

3

versuchen, diese:

doSomething(unsigned char *buffer) 
{  
    Socket.recv((char *)buffer); 
    printout(buffer); 
} 

Edit: Ja, zuteilen zuerst etwas Speicher für Puffer vor doSomething Aufruf.

Edit 2: Wenn Sie Speicher in doSomething zuordnen wollen, dann:

doSomething(unsigned char **buffer) 
{ 
    *buffer = malloc(MAX_LENGTH_SOCKET_RECV_MAY_RETURN); 
    Socket.recv((char *)(*buffer)); 
    printout(*buffer); 
} 

und rufen Sie wie folgt aus:

doSomething(&buffer); 
2

In C/C++ können Sie keine char* zu einem anderen zuweisen um Speicher zu kopieren. Sie müssen ein Strncpy über die receiveddata in die buffer machen.

2

Das Argument wird durch den Wert übergeben - 'Puffer' im Anrufer hat immer noch den gleichen Wert nach dem Anruf, den es vorher hatte. Die Änderungen am gleichnamigen Parameter in der Funktion haben keinen Einfluss darauf.

0

Sie müssen einen gültigen Puffer bereitstellen, in dem recv( Daten gespeichert werden.

Try this:

unsigned char buffer[512] 

doSomething(buffer); 

... 

void doSomething(unsigned char* buffer) 
{ 
    Socket.recv(buffer); 
    printout(buffer) 
} 
+0

Smelly Code. Wo wird 'recv' angegeben? Woher weißt du, dass es nicht mehr als 512 Bytes schreiben wird? Oder, da es nicht einmal die Puffergröße braucht, den Puffer selbst zuweisen? – sbi

5

Sie haben zwei Probleme:

  1. Der Zeiger receiveddata nicht initialisiert ist und somit zeigt auf einige zufällige Stelle im Speicher. Dies führt dazu, dass Sie irgendwo Daten löschen.

  2. Die Änderung, die Sie an den Zeiger buffer vornehmen, wird nicht nach außen weitergegeben. Wenn Sie dies tun möchten, müssen Sie einen Doppelzeiger verwenden.

Hier ist eine Lösung für beide Probleme:

void doSomething(unsigned char **buffer) 
{  
    unsigned char* receiveddata; 

    // Allocate memory 
    // Note: You need to know the maximum length of data that you will 
    // ever receive here. 
    receiveddata=new unsigned char[MAXIMUM_NUMBER_OF_CHARS_YOU_WILL_RECEIVE]; 

    Socket.recv(receiveddata); 
    *buffer = receiveddata; 
    printout(buffer); 
} 

Beachten Sie, dass dieser Code zu einem Pufferüberlauf-Angriff, falls jemand anfällig ist, kann es mehr Daten senden, als Sie erwarten. Welche Socket-Bibliothek verwenden Sie? Verfügt sie über einen Mechanismus, der Sie davor schützen kann, mehr Daten in den Puffer zu schreiben, als es möglich ist (z. B. ein zusätzliches Argument, um die Länge des Puffers anzugeben)?

Sie würden dies nennen wie folgt:

unsigned char* buffer;  
doSomething(&buffer); 
// Process the data in buffer, then free it when you're done: 
delete [] buffer; 

jedoch, wie andere haben darauf hingewiesen, es ist umständlich Speicherzuweisung und Löschen selbst zu verwalten. Sehen Sie sich die Standardbibliothek und die darin enthaltenen String- und Collection-Klassen an - diese können das Leben einfacher und sicherer machen, indem Sie die Speicherverwaltung für Sie übernehmen.

Bearbeitet wie in den Kommentaren notiert.

+2

Urgh. Nun teilt diese Funktion Speicher aus, den sie anderen zum Löschen zuweist. Und was bringt es, 'malloc' anstelle von' new' zu verwenden? Das Problem wurde schließlich mit "C++" markiert. Was denkst du wird passieren, wenn andere versuchen, diese Erinnerung zu löschen? Und woher wissen Sie, 256 Bytes sind genug? (Was ist das 'Socket.recv()' Ding trotzdem?) – sbi

+0

All das sind gute Punkte ... Schätze, ich war in einem C Mindeset wegen all der Zeiger, aber du hast natürlich recht, das sollte new/delete anstelle von malloc/free (fixed) verwenden. Das Verteilen von Erinnerungen ist kein schönes Idiom, aber es schien zu sein, was Floh wollte, weshalb ich dabei blieb. 256 Bytes reichen natürlich nicht aus - der Code wurde geändert, um dies zu unterstreichen. –

-1

Alternativ:

#define MAX_RECV_OUTPUT_LENGTH 1024 // See comment below at recv() call. 
char *buffer = new char[MAX_RECV_OUTPUT_LENGTH]; 
doSomething(buffer); 
printout(buffer); 
delete[] buffer; 

void doSomething(char *buffer) 
{  
    Socket.recv(buffer); // Ideally you would know how much memory you need (exactly or MAX, as specified by API). 
} 

So:

  • Sie selbst zuweisen müssen, sei es mit neuen/löschen oder malloc()/free() (oder als offensichtlich wurde, durch einen Behälter).
  • Das Zuweisen eines Zeigers zu einem anderen ändert nur die Adresse, auf die gezeigt wird, es kopiert keine Daten.
  • Wenn es sich um eine Zeichenfolge handelt, benötigen Sie die nicht signierte Zeichenfolge? Just checking ..
  • Und sehr viel wie jemand anders nur gesagt: wir alle nehmen recv() isst einen Zeiger zu schreiben, aber das könnte anders sein? Wir müssen wissen.
+0

Woher wissen Sie, dass die 'recv'-Funktion keinen Puffer zuweist? Und wenn nicht, woher weißt du, dass es nur 256 Bytes schreibt? Und was, wenn "Ausdruck" werfen könnte? Es tut mir leid zu sagen, aber ich betrachte diesen schlecht riechenden Code. – sbi

+0

Der Kommentar deutet darauf hin, dass dies nur ein Beispiel dafür ist, wie man vereinfacht, was getan wird. Das sollte in dieser Hinsicht nicht stimmen. Überprüfen Sie außerdem den letzten Aufzählungspunkt. – nielsj

+0

@sbi: Wenn recv() Puffer selbst alllocate ist, dann muss sein Argument ein Doppelzeiger sein. – palindrom