My program gives different results on different machines ..!

#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; } 

for any input, it must concatenate 0000 with this line, but on one PC it shows the diamond sign between "0000" and the input line ...!

+6
source share
5 answers

You add to the nine-character line (which contains four characters and without line terminator) the ninth (or more, gets do not have border checks) character line). No line breaks. Therefore, when you type with puts , it will continue to type until it finds a line termination character that can be anywhere in memory. In short, an example of a schoolbook buffer overflow, and a buffer overflow usually results in the undefined behavior that you see.

In C and C ++, all C-style lines must be completed. They end with a special character: '\0' (or a plain ASCII zero). You also need to provide enough space for the destination string in your strcat call.


Proper work program:

 #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; } 
+6
source

There are two problems in the code.

First, left does not have nul-terminated, so strcat will end the scan outside the array with a suitable place to add characters. Put a '\0' at the end of the array.

Secondly, left not large enough to hold the result of calling strcat . There should be enough space for the resulting string, including the nul terminator. Therefore, the size of left must be at least 4 + 9 to allow three characters (plus nul terminator), with which left begins, and 9 characters following from str (provided that gets caused an overflow).

Each of these errors results in undefined behavior that takes into account different results on different platforms.

+2
source

I don’t know why you are worried about including <iostream> , since you are not using any C ++ features in your code. Your whole program would be much shorter if you had:

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

Since std::string will have a null termination, there is no reason to force it to terminate with 4 zeros.

+1
source

Problem number 1 is not the legal line:

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

The string must end with zero char, '\0' not '0' . This leads to what you are describing.

Problem number 2 - fgets . You use it on a small buffer. Very dangerous.

Problem number 3 is strcat . And again, an attempt to fill a super-small buffer that should have been filled with an extra line.

This code looks like a buffer overflow invitation.

0
source

In C, what we call a string is an array of characters with a null terminating character. All functions in the string.h library are based on this null value at the end of the character array. Your character array is not null-terminated and therefore not a string, so you cannot use the strcat string library function here.

0
source

All Articles