1

The following code seems to be running when it shouldn't. In this example:

#include <iostream>
using namespace std;
int main()
{
    char data[1];
    cout<<"Enter data: ";
    cin>>data;
    cout<<data[2]<<endl;
}

Entering a string with a length greater than 1 (e.g., "Hello"), will produce output as if the array were large enough to hold it (e.g., "l"). Should this not be throwing an error when it tried to store a value that was longer than the array or when it tried to retrieve a value with an index greater than the array length?

mattsbox
  • 91
  • 1
  • 5

3 Answers3

3

The following code seems to be running when it shouldn't.

It is not about "should" or "shouldn't". It is about "may" or "may not".

That is, your program may run, or it may not.

It is because your program invokes undefined behavior. Accessing an array element beyond the array-length invokes undefined behavior which means anything could happen.

The proper way to write your code is to use std::string as:

#include <iostream>
#include <string>

//using namespace std;  DONT WRITE THIS HERE

int main()
{
    std::string data;
    std::cout<<"Enter data: ";

    std::cin>>data; //read the entire input string, no matter how long it is!

    std::cout<<data<<std::endl; //print the entire string

    if ( data.size() > 2 ) //check if data has atleast 3 characters
    {
         std::cout << data[2] << std::endl; //print 3rd character 
    }
}
razlebe
  • 7,134
  • 6
  • 42
  • 57
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • 1
    Sounds good, thanks a bunch. I assumed the defined behavior was to cut off the string or throw an exception. Thanks for the clarification – mattsbox Jun 12 '12 at 08:25
1

It can crash under different parameters in compilation or compiled on other machine, because running of that code giving undefined result according to documentaton.

Svisstack
  • 16,203
  • 6
  • 66
  • 100
1

It is not safe to be doing this. What it is doing is writing over the memory that happens to lie after the buffer. Afterwards, it is then reading it back out to you.

This is only working because your cin and cout operations don't say: This is a pointer to one char, I will only write one char. Instead it says: enough space is allocated for me to write to. The cin and cout operations keep reading data until they hit the null terminator \0.

To fix this, you can replace this with:

std::string data;

C++ will let you make big memory mistakes.

Some 'rules' that will save you most of the time:

1:Don't use char[]. Instead use string.

2:Don't use pointers to pass or return argument. Pass by reference, return by value.

3:Don't use arrays (e.g. int[]). Use vectors. You still have to check your own bounds.

With just those three you'll be writing some-what "safe" code and non-C-like code.

Rhexis
  • 2,414
  • 4
  • 28
  • 40
  • I'm strongly tempted to give a -1 for the "allocate a large array" 'solution' to buffer overflows. –  Jun 12 '12 at 08:11
  • Would you like me to remove it? – Rhexis Jun 12 '12 at 08:11
  • I think it would be a good idea to either remove it, or at least to introduce the iostream mechanisms to ensure that you don't read more characters than your buffer can hold. I think `std::setw` will work in this situation? I haven't used the manipulators for input very often. –  Jun 12 '12 at 08:12