1
//SECTION I:
void main()
{
    char str[5] = "12345";  //---a)
    char str[5] = "1234";   //---b)
    cout<<"String is: "<<str<<endl;
}
Output: a) Error: Array bounds Overflow.
        b) 1234

//SECTION II:
void main()
{
    char str[5];
    cout<<"Enter String: ";
    cin>>str;
    cout<<"String is: "<<str<<endl;
}

I tried with many different input strings, and to my surprise, I got strange result:

Case I: Input String: 1234, Output: 1234 (No issue, as this is expected behavior)

Case II: Input String: 12345, Output: 12345 (NO error reported by compiler But I was expecting an Error: Array bounds Overflow.)

Case III: Input String: 123456, Output: 123456 (NO error reported by compiler But I was expecting an Error: Array bounds Overflow.)

.................................................

.................................................

Case VI: Input String: 123456789, Output: 123456789(Error: unhandeled exception. Access Violation.)

My doubt is, When I assigned more characters than its capacity in SECTION I, compiler reported ERROR: Array bounds Overflow.

But, when I am trying the same thing in SECTION II, I am not geting any errors. WHY it is so ?? Please note: I executed this on Visual Studio

Jatin
  • 1,857
  • 4
  • 24
  • 37
  • @chris, I didn't know that this was the reason for unexpected behaviors :) – Jatin Apr 24 '12 at 11:25
  • It's not. That's why it's a comment and not an answer. – chris Apr 24 '12 at 11:26
  • why not just use `char str[]="12345";`? – hochl Apr 24 '12 at 11:28
  • @chris You are wrong. [Read this](http://stackoverflow.com/questions/5296163/why-is-the-type-of-the-main-function-in-c-and-c-left-to-the-user-to-define/5296593#5296593). – Lundin Apr 24 '12 at 11:36
  • @Lundin, it is a good read. However, the chances that anyone who posts using it, unless they say otherwise, are not on a hostless system. It's more a bad habit picked up from several old books. – chris Apr 24 '12 at 11:39
  • @Lundin You want me to believe code above is a first attempt to write some OS? – Tadeusz Kopec for Ukraine Apr 24 '12 at 11:42
  • @TadeuszKopec No, but it may very well be the first attempt to write an embedded system. There is a whole world filled with computers out there, beyond the Windows desktop. – Lundin Apr 24 '12 at 11:47
  • @chris I wouldn't make any assumptions about the used platform unless indicated by the OP. There are plenty of beginners writing similar programs for embedded systems. – Lundin Apr 24 '12 at 11:49
  • @Lundin Note that programs __for__ embedded systems are not hostless, so main should return `int` – Eregrith Apr 24 '12 at 12:01
  • @Eregrith Embedded systems is a very wide area. Could be anything from tiny barebone 8-bit MCUs to Smartphone fluff. If there is an OS beneath your program, main should indeed return int. – Lundin Apr 24 '12 at 12:30
  • yes but what I meant is: if an embedded system's program is considered hostless, the program is not __for__ the embedded system, it __is__ the embedded system – Eregrith Apr 24 '12 at 16:26

6 Answers6

4
char str[5] = "12345";

This is a compiletime error. You assign a string of length 6 (mind the appended null-termination) to an array of size 5.


char str[5];
cin>>str; 

This may yield a runtime error. Depending on how long the string is you enter, the buffer you provide (size 5) may be too small (again mind the null-termination).


The compiler of course can't check your user input during runtime. If you're lucky, you're notified for an access violation like this by Segmentation Faults. Truly, anything can happen.

Throwing exceptions on access violations is not mandatory. To address this, you can implement array boundary checking yourself, or alternatively (probably better) there are container classes that adapt their size as necessary (std::string):

std::string str;
cin >> str;
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
  • I agree that compiler can't check user's input. But once I have assigned more than its limit. it should throw an ERROR. My doubt is--Why I didnt get any exception at CASE II and why I got an exception only from CASE VI onwards??? ......if C++ runtime is capable of throwing an error at caseVI, it should be thrown right at CASE II. – Jatin Apr 24 '12 at 11:29
  • @VikasChhipa, two things: 1. It's undefined whether an error will occur or not. In case VI, it happened to run into an access violation error because it happened to do so since you were running off the end of the array. 2. Arrays are not capable of catching errors. They are a lower-level data type built for speed over any sort of extra error checking. – chris Apr 24 '12 at 11:32
  • @VikasChhipa Throwing exceptions on access violations is not mandatory. You can implement array boundary checking and there are container classes that adapt their size as necessary (`std::string`). But you don't get what you don't pay for. Welcome to C/C++. – moooeeeep Apr 24 '12 at 11:34
  • OK chris and moooeeeep. will keep your comments in mind. AND @moooeeeep......typing your name correctly is tedious job. I need to write a separate program who will count the number or O's and E's ;-) – Jatin Apr 24 '12 at 11:43
  • -1 Since you don't explain _why_ these two lines are errors. This isn't helping the OP to solve the problem nor is it helping future visitors. – Lundin Apr 24 '12 at 11:46
4

What you are seeing is an undefined behavior. You are writing array out of bounds, anything might happen in that case ( (including seeing the output you expect).

Naveen
  • 74,600
  • 47
  • 176
  • 233
3

I tried with many different input strings, and to my surprise, I got strange result:

This phenomena is called Undefined behavior (UB).

As soon as you enter more characters than a char array can hold, you invite UB.
Sometime, it may work, it may not work sometime, it may crash. In short, there is no definite pattern.

[side note: If a compiler allows void main() to get compiled then it's not standard compliant.]

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • You are wrong, void main() is perfectly fine by the standard. [Read this](http://stackoverflow.com/questions/5296163/why-is-the-type-of-the-main-function-in-c-and-c-left-to-the-user-to-define/5296593#5296593). – Lundin Apr 24 '12 at 11:50
  • @Lundin, **no**. `void main()` is not correct. [see here](http://www2.research.att.com/~bs/bs_faq2.html#void-main). – iammilind Apr 24 '12 at 11:54
2

It's because in the second case, the compiler can't know. Only at runtime, there is a bug. C / C++ offer no runtime bounds checking by default, so the error is not recognized but "breaks" your program. However, this breaking doesn't have to show up immediately but while str points to a place in memory with only a fixed number of bytes reserved, you just write more bytes anyways.

Your program's behavior will be undefined. Usually, and also in your particular case, it may continue working and you'll have overwritten some other component's memeory. Once you write so much to access forbidden memory (or free the same memory twice), your program crashes.

b.buchhold
  • 3,837
  • 2
  • 24
  • 33
2

char str[5] = "12345" - in this case you didn't leave room to the null terminator. So when the application tries to print str, it goes on and on as long as a null is not encountered, eventually stepping on foridden memory and crashing.

In the `cin case, the cin operation stuffed 0 at the end of the string, so this stops the program from going too far in memory.

Hoever, from my experience, when breaking the rules with memory overrun, things go crazy, and looking for a reason why in one case it works while in other it doesn't, doesn't lead anywhere. More often than not, the same application (with a memory overrun) can work on one PC and crash on another, due to different memory states on them.

Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
1

because compiler does static check. In your section II, size is unknown in advance. It depends on your input length.

May i suggest you to use STL string ?

URaoul
  • 523
  • 3
  • 13