2017-04-21 5 views
1

So arbeite ich derzeit an einer Zuordnung und auf meinem Laptop funktioniert es gut, aber auf meinem PC ist der Ausgang Kauderwelsch.C++ verschiedene Ausgabe aus dem gleichen Programm auf zwei Systeme

Geben Sie einen Befehl:
ein
einen Befehl eingeben:
a'Zéÿ Befehl empfangen.

Ignorieren meiner vermasselten Ausgabe warum gibt es eine'Zéÿ in der Ausgabe?
Auf meinem Laptop funktioniert der Code wie vorgesehen.

Hier ist ein kleiner Beispielcode:

#include <sys/types.h> 
#include <sys/wait.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <iostream> 
using namespace std; 

int main(){ 
    int pipefd[2]; 
    pid_t cpid, ppid; 
    char buf[100]; 

    if (pipe(pipefd) == -1) { 
     perror("pipe"); 
     exit(EXIT_FAILURE); 
    } 

    cpid = fork(); 

    if (cpid == 0) { 
     read(pipefd[0], &buf, 1); 
     cout << buf << " command received." << endl; 
    } 
    else { 
     cout << "Enter a command: " << endl; 
     cin >> buf; 
     cout << "buf: " << buf << endl; 
     size_t len = strlen(buf); 
     write(pipefd[1], &buf, len); 
    } 

    return 0; 
} 

Der Ausgang ist slighty Differnt obwohl sein nur
ein `Befehl empfing. anstelle von
ein Befehl erhalten.

E: Ich bin Antergos auf meinem PC und elementar auf meinem Laptop, auf beiden Systemen das Terminal urxvt

Antwort

1
read(pipefd[0], &buf, 1); 

liest ein Byte. Da es ein Byte ist, ist es unwahrscheinlich, dass das Programm des Nullabschluss von

cout << buf << " command received." << endl; 

So Druck ist nicht definiertes Verhalten erforderlich gelesen hat; operator<< weiß nicht, wo Sie aufhören zu lesen. Es könnte sofort aufhören, es könnte am Ende des gültigen Speichers laufen und das Programm zum Absturz bringen. Es gibt keine Möglichkeit, sicher zu sein, und die Ergebnisse könnten jedes Mal anders sein.

Da es keine Protokollinformationen in der Frage ist, ist mein einziger Vorschlag ein Kommunikationsprotokoll zu etablieren, die den Leser, wie viele Bytes informiert gelesen werden müssen. Ich möchte einen Zähler bekannter Größe senden, um den Leser über die Größe der Nachricht zu informieren, bevor die Nachricht gesendet wird. Zum Beispiel

uint32_t len = strlen(buf); 
write(pipefd[1], &len, sizeof(len)); 
write(pipefd[1], &buf, len); 

und dann lesen

uint32_t len; 
read(pipefd[0], &len, sizeof(len)); 
read(pipefd[0], &buf, len); 

Vergessen Sie nicht, dass die Lese gelungen und bekam die Anzahl von Bytes, die Sie benötigen. Möglicherweise müssen Sie den Lesevorgang wiederholen, bis Sie die gesamte Nachricht erhalten. hat

+0

Ein gutes Protokoll ist nicht auf die Nachrichtenlänge angewiesen, da der Empfänger weniger als die Anzahl der Ziffern erhalten kann gesendet, um mit zu beginnen. Eine bessere Methode ist die Verwendung eines Trennzeichens. json ist ein gutes Beispiel für '{message}'. – alvits

+0

@alvits Kommt ganz auf die Bedürfnisse des Protokolls an. Der Delimiter-Ansatz erfordert ein Lesemuster von GETTA-Byte GETTA-Byte GETTA Byte, Byte, Byte, um das Trennzeichen zu finden, und das ist möglicherweise nicht geeignet. Sie können den Eingabepuffer für eine Sache sorglos überlaufen. Die vorangestellte Länge ermöglicht es dem Empfänger, die Zeit im Voraus zu überprüfen und sicherzustellen, dass sie genügend Speicher haben, um die Nachricht zu verarbeiten und hoffentlich einen großen Lesevorgang zu machen. – user4581301

+0

Ich stimme nicht zu. Deshalb gibt es den dritten Parameter für 'read()'. Dies ist der Schutz vor Pufferüberlauf. Der Absender darf länger senden als der Puffer halten kann. Der Empfänger ist dafür verantwortlich, alles über eine Schleife zu lesen, wenn der Puffer kürzer ist. – alvits

2

Sie haben die Puffer zu initialisieren oder sonst wird es enthalten, was vorher an dieser Stelle in Erinnerung war , was gedruckt wird.

+0

Aber warum funktioniert es auf meinem Laptop in Ordnung, die mich – user273032

+0

verwirrt Es kommt alles dem Zufall: auf Ihrem Laptop, muss es nicht druckbare Zeichen im Speicher an diesem Ort sein. –

+0

@ user273032 undefined Verhalten ist nicht definiert. Es könnte sogar so aussehen, als ob es funktioniert. – user4581301

1

read() nicht automatisch ein Null-Byte anhängen. Es liegt in Ihrer Verantwortung, am Ende der empfangenen Nachricht ein Nullbyte anzuhängen.

Am einfachsten ist es, den Wert von read() zurück zu bekommen. Dieser Wert ist die Anzahl der gelesenen Bytes oder -1, wenn ein Fehler aufgetreten ist. Verwenden Sie diesen Rückgabewert, um das Ende der Zeichenfolge auf null festzulegen.

Ändern Sie diese Zeile:

read(pipefd[0], buf, 1); 

An:

int length=read(pipefd[0], buf, 99); 
if (length > 0) // length bytes was read 
    buf[length]='\0'; 
else // nothing was read or an error occured 
    buf[0]='\0'; 

Alternativ können Sie Null nur den gesamten Puffer, so dass Sie nicht ein Null-Byte anhängen müssen.

diese Änderung:

read(pipefd[0], buf, 1); 

Um dies:

memset(buf,0,100); 
read(pipefd[0], buf, 99); 
Verwandte Themen