2009-07-26 17 views
6

Wenn Daten über eine Socket empfangen recv Verwendung Ich habe festgestellt, dass, mit:char Array vs. char Zeiger

 
char buffer[4]; 
memset(buffer, 0, 4); 
recv(socket, buffer, 4, 0); 

I

mesgx

erhalten

"mesg" ist was ich gesendet habe, mit einigen zufälligen Zeichen angehängt.

Wenn ich

 
char * method = (char *) malloc(4); 
memset(buffer, 0, 4); 
recv(socket, buffer, 4, 0); 

stattdessen erhalte ich

mesg

So gibt es keine zufälligen Sachen meinen String angehängt. Ich habe herausgefunden, dass wenn ich char [5] benutze, es auch funktioniert, aber ich verstehe nicht wirklich warum. Ordnet malloc (4) wirklich 5 Bytes zu, wobei der fünfte ein NUL ist?

Antwort

16

Der Aufruf an malloc(4) teilt wirklich nur vier Bytes zu. Es war nur Zufall, dass das nächste Byte im Speicher zufällig ein NUL war, der Ihre Zeichenfolge für Sie beendete.

In dem Fall, in dem Sie char buffer[4] auf dem Stack zugewiesen haben, ist das nächste Byte ein 'x' gefolgt von einigen anderen Sachen, so dass Ihre Zeichenfolge fortgesetzt wurde, bis das nächste NUL-Byte gefunden wurde.

Socket-Funktionen behandeln nur Bytes und behandeln die Bytes nicht als Strings mit einem abschließenden NUL oder irgendetwas Zusätzlichem. Sie bekommen genau das, wonach Sie fragen.

6

Sie benötigen 5 Zeichen, um ordnungsgemäß NULL beendet zu werden. Der abschließende NULL zählt als Eins. Wenn also N Zeichen benötigt werden, muss N + 1 zugewiesen werden. Oder umgekehrt, für eine Zuweisung von N haben Sie N-1 für Ihre Inhalte zur Verfügung.

+0

Ich dachte so viel, aber warum funktioniert es dann mit malloc? – fresskoma

2

Sie können nicht mehr als 4 char s empfangen haben, da Sie nur recv für maximal 4 Bytes angefordert haben, um in Ihren Puffer platziert zu werden. Sie sollten den Rückgabewert von recv überprüfen, um zu sehen, wie viele Bytes tatsächlich zurückgegeben wurden.

Ich vermute, dass das Problem ist, dass Sie nicht vorsichtig sind, nur 4 char s aus was Routine generiert die Ausgabe ausgeben. Eine Möglichkeit, die anfänglichen Inhalte eines möglicherweise nicht nullterminierten char-Puffers anzuzeigen, ist dies.

printf("%.4s\n", buffer); 

Ein kompletter recv Aufruf Snippet könnte sein:

#define MAX_BUF_LEN (512) 
char buffer[MAX_BUF_LEN]; 
ssize_t count = recv(socket, buffer, MAX_BUF_LEN, 0); 

if (count > 0) 
    printf("%.*s\n", count, buffer); 
3

Ich vermute, dass der Unterschied ein Zufall ist. Wenn Sie den Puffer als Zeichenfolge verwenden, zum Beispiel in printf(), wird er über sein Limit hinaus gelesen, bis ein '\ 0' gefunden wird.

In beiden Fällen sollten Sie Puffer [5] oder malloc (5) verwenden. Das memset() sollte nicht notwendig sein, besser einen Puffer [4] = '\ 0' nach dem recv() setzen.