Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My program is giving different output 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 should concatenate 0000 with that string, but on one pc it's showing a diamond sign between "0000" and the input string...!

like image 698
CapeAndCowl Avatar asked Dec 16 '13 14:12

CapeAndCowl


1 Answers

You append a possible nine (or more, gets have no bounds checking) character string to a three character string (which contains four character and no string terminator). No string termination at all. So when you print using puts it will continue to print until it finds a string termination character, which may be anywhere in memory. This is, in short, a school-book example of buffer overflow, and buffer overflows usually leads to undefined behavior which is what you're seeing.

In C and C++ all C-style strings must be terminated. They are terminated by a special character: '\0' (or plain ASCII zero). You also need to provide enough space for destination string in your strcat call.


Proper, working 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;
}
like image 175
Some programmer dude Avatar answered Sep 30 '22 12:09

Some programmer dude