2013-12-16 2 views
6
#include<iostream> 
#include<string.h> 
#include<stdio.h> 


int main() 
{ 
    char left[4]; 
    for(int i=0; i<4; i++) 
    { 
     left[i]='0'; 
    } 
    char str[10]; 
    gets(str); 
    strcat(left,str); 
    puts(left); 
    return 0; 
} 

für jede Eingabe sollte es 0000 mit dieser Zeichenfolge verketten, aber auf einem PC zeigt es ein Rautenzeichen zwischen "0000" und der Eingabezeichenfolge ...!Mein Programm gibt unterschiedliche Ausgabe auf verschiedenen Maschinen ..!

+5

Sie befinden sich über das Ende Ihres Puffers hinaus. Das ist in der Tat undefiniertes Verhalten. –

+3

Funktion [gets()] (http://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) ist veraltet und gefährlich, don benutze es nicht. – this

+2

left ist keine Null-terminierte Zeichenfolge. Sie müssen char left [5] definieren; und dann nach der Schleife hinzufügen links [4] = 0; // Note 0 und nicht '0' –

Antwort

6

Sie fügen eine neun (oder mehr, gets haben keine Grenzen überprüfende) Zeichenkette an eine drei Zeichen lange Zeichenfolge an (die vier Zeichen und kein Zeichenfolgenabschlusszeichen enthält). Kein String Terminierung überhaupt. Wenn Sie also mit puts drucken, wird so lange gedruckt, bis ein Zeichenkettenbeendigungszeichen gefunden wird, das irgendwo im Speicher sein kann. Dies ist, kurz gesagt, ein Schulbuchbeispiel von Pufferüberlauf, und Pufferüberläufe führen normalerweise zu undefined Verhalten was Sie sehen.

In C und C++ müssen alle C-Style-Strings beendet werden. Sie werden durch ein Sonderzeichen beendet: '\0' (oder ASCII-Null). Sie müssen außerdem genügend Speicherplatz für die Zielzeichenfolge in Ihrem strcat-Aufruf bereitstellen.


Proper, Arbeitsprogramm:

#include <stdio.h> 
#include <string.h> 
#include <errno.h> 

int main(void) 
{ 
    /* Size is 4 + 10 + 1, the last +1 for the string terminator */ 
    char left[15] = "0000"; 
    /* The initialization above sets the four first characters to '0' 
    * and properly terminates it by adding the (invisible) '\0' terminator 
    * which is included in the literal string. 
    */ 

    /* Space for ten characters, plus terminator */ 
    char str[11]; 

    /* Read string from user, with bounds-checking. 
    * Also check that something was truly read, as `fgets` returns 
    * `NULL` on error or other failure to read. 
    */ 
    if (fgets(str, sizeof(str), stdin) == NULL) 
    { 
     /* There might be an error */ 
     if (ferror(stdin)) 
      printf("Error reading input: %s\n", strerror(errno)); 
     return 1; 
    } 

    /* Unfortunately `fgets` may leave the newline in the input string 
    * so we have to remove it. 
    * This is done by changing the newline to the string terminator. 
    * 
    * First check that the newline really is there though. This is done 
    * by first making sure there is something in the string (using `strlen`) 
    * and then to check if the last character is a newline. The use of `-1` 
    * is because strings like arrays starts their indexing at zero. 
    */ 
    if (strlen(str) > 0 && str[strlen(str) - 1] == '\n') 
     str[strlen(str) - 1] = '\0'; 

    /* Here we know that `left` is currently four characters, and that `str` 
    * is at most ten characters (not including zero terminaton). Since the 
    * total length allocated for `left` is 15, we know that there is enough 
    * space in `left` to have `str` added to it. 
    */ 
    strcat(left, str); 

    /* Print the string */ 
    printf("%s\n", left); 

    return 0; 
} 
+3

ich es nennen würde„Schulbuch Beispiel für * Pufferüberlauf * ". Weniger allgemeiner Begriff. – jrok

0

Problem # 1 - kein Recht string:

char left[4]; 
for(int i=0; i<4; i++) 
{ 
    left[i]='0'; 
} 

String mit einem Null-Zeichen enden muss, '\0' nicht '0'. Dies verursacht, was Sie beschreiben.

Problem # 2 - fgets. Sie verwenden es in einem kleinen Puffer. Sehr gefährlich.

Problem # 3 - strcat. Versuchen Sie noch einmal, einen sehr kleinen Puffer zu füllen, der bereits mit einer zusätzlichen Zeichenfolge gefüllt sein sollte.

Dieser Code sieht eine Einladung zu einem Pufferüberlauf-Angriff aus.

0

In C, was wir einen String nennen, handelt es sich um ein nullterminiertes Zeichenarray. Alle Funktionen in der string.h-Bibliothek basieren auf diesem Nullwert am Ende des Zeichenarrays. Ihr Zeichenarray ist nicht nullterminiert und ist somit kein String, Sie können hier also nicht die String-Bibliothek strcat verwenden.

2

Es gibt zwei Probleme im Code.

Zuerst left ist nicht nullterminiert, so strcat wird am Ende über das Ende des Arrays für die entsprechende Stelle zum Anhängen von Zeichen enden. Setzen Sie eine '\0' am Ende des Arrays.

Zweitens ist left nicht groß genug, um das Ergebnis des Aufrufs an strcat zu halten. Es muss genügend Platz für die resultierende Zeichenfolge einschließlich des Nullabschlusses sein. So sollte die Größe von left mindestens 4 + 9, für die drei Zeichen (plus null Terminator), die left beginnt mit, und 9 Zeichen aus str (vorausgesetzt, dass gets hat keinen Überlauf verursacht) zu ermöglichen.

Jeder dieser Fehler führt zu undefiniertem Verhalten, das für die unterschiedlichen Ergebnisse auf verschiedenen Plattformen verantwortlich ist.

1

Ich weiß nicht, warum Sie <iostream> wie Sie C++ Funktionen in Ihrem Code verwenden, sind nicht enthalten stört. Ihr gesamtes Programm wäre viel kürzer, wenn Sie hatte:

#include <iostream> 
#include <string> 

int main() 
{ 
    std::string line; 
    std::cin >> line; 
    std::cout << "You entered: " << line; 
    return 0; 
} 

Da std::string wird nullterminierte sein, gibt es keinen Grund, sie zu zwingen, 4-nullterminierte zu sein.