saeed mahmoodi
saeed mahmoodi

Reputation: 73

cin memory safety

please take a look at this code

#include <iostream>

int main(int argc, char** argv) {
    char ch[10];
    int i = 0;
    std::cout << "Enter a number: \n";
    std::cin >>ch;


    std::cout << "i = "<<i;

}

output:

Enter a number:
123456789123456789
i = 926299444

why this is happend and what is the best way to prevent this ?

where can i learn more about this kind of unsafety ?

Upvotes: 0

Views: 1171

Answers (1)

walnut
walnut

Reputation: 22152

Your program has undefined behavior, because you are writing out-of-bounds of ch. One possible manifestation of this is that your program behaves as if an unrelated variable was overwritten. This particular kind of undefined behavior is known as a stack buffer overflow.

The >> only gets a pointer to the first element of the ch array as argument and so it doesn't know how long the array is and will just keep writing no matter how long the user's input is. This behavior known as array-to-pointer decay is normal for raw arrays (but unintuitive). This is why you should avoid using them.

It is never safe to use a char pointer or array with cin >> if you don't know apriori the maximum length of the input. As mentioned in a comment below, this is why this overload will be removed in the upcoming C++20 standard, so that you will get a compile-time error, rather than the undefined behavior at runtime that you are observing.

The solution is simple: Don't use char arrays. Use std::string instead.

#include <iostream>
#include <string>

int main(int argc, char** argv) {
    std::string ch;
    int i = 0;
    std::cout << "Enter a number: \n";
    std::cin >> ch;

    std::cout << "i = " << i;
}

std::string can hold any length of string and will allocate and manage the required memory itself.


Also note that you can read numbers directly into integers (which seems to be what you actually want to do):

#include <iostream>

int main(int argc, char** argv) {
    int i = 0;
    std::cout << "Enter a number: \n";
    std::cin >> i;

    std::cout << "i = " << i;
}

This will fail if the number is too large for int to hold it or if the user tries to input something that isn't a number, so you should check whether it failed. You should always check the input functions for failure, like this:

#include <iostream>

int main(int argc, char** argv) {
    int i = 0;
    std::cout << "Enter a number: \n";
    if(!(std::cin >> i)) {
        // handle error here
        std::cout << "You must insert a valid number in the range of int!\n";
        return 1; // exit `main` with return value indicating error
    }

    std::cout << "i = " << i;
}

Upvotes: 4

Related Questions