1

Given a string , say ,

char *str = "Hello,StackOverflow!"
char newStr[30];
int l = strlen(str);
for(int i =0 ; i<l ; i ++ )
   newStr[i] = str[i];
printf("%s" , newStr);

Now , we know that the last character of a c-string has to be '\0' , Since here we haven't explicitly done the same ( store '\0' at last index of string newStr) , this program should crash since printf won't find the end of string.

But I noticed that it was working fine sometimes and sometimes it wasn't. What could be the problem ? It was working almost everytime actually. Isn't it supposed to crash or give some run-time error?

Will it be the same case in C++ too ?

h4ck3d
  • 6,134
  • 15
  • 51
  • 74
  • What is your definition of "crash"? What do you expect to happen? – Josh Petitt Sep 17 '12 at 16:17
  • @KerrekSB Sorry , that was supposed to be newStr. – h4ck3d Sep 17 '12 at 16:20
  • The "anything might happen" answers are a bit sensationalist. You could speculate that the `printf` routine will continue to print until it hits an unrelated zero byte, which is often soon enough. Strictly speaking, it will likely be accessing memory outside the program's designated memory block, but blocks are fairly coarsely allocated, so you might not get an access violation most of the time. – tripleee Sep 17 '12 at 16:42
  • 1
    @sTEAK., to address your other comments about how to alter you code, look at strcpy, or its brother strncpy, http://www.cplusplus.com/reference/clibrary/cstring/strcpy/ – Josh Petitt Sep 17 '12 at 18:46

6 Answers6

7

No. It invokes undefined behavior - it means it doesn't have to crash - it can do literally anything, like nasal demons.

Also, "gives a runtime error" - well, that depends on what do you mean by a runtime error. There's no dynamic runtime for C - if you expect a nicely formatted error message from an exception, that wouldn't happen. What would happen is most likely a segmentation fault.

All in all, if one causes/uses undefined behavior, he must not rely on it crashing or not crashing.

  • @JoshPetitt unexpected, abnormal termination of a program due to it having semantic errors. –  Sep 17 '12 at 16:22
  • does '\0' get added explicitly or not at the end of string newStr ? – h4ck3d Sep 17 '12 at 16:30
  • 1
    @sTEAK. no, it doesn't - as you correctly expect, strlen() returns the string length **without** the terminating 0, so it doesn't get copied over. –  Sep 17 '12 at 16:31
  • @H2CO3, that is a reasonable definition that I think lies at the heart of the OP's question. The OP should think about what a "crash" is and what could cause a "crash". Like you've said, the access violation is probably the most likely to occur, but this is a secondary effect of undefined behavior, not the direct effect of the code being executed. +1 for nasal demons :-) – Josh Petitt Sep 17 '12 at 18:40
  • @JoshPetitt right. I just thought I quite understood what OP meant about what a crash is :) –  Sep 17 '12 at 19:01
3

A "crash" is not guaranteed. A program that improperly handles null terminators in strings - more generally accesses data outside of buffer boundaries - or violates the printf format string, may seem to work just fine, functioning and not e.g. causing a segfault. But this is just happenstance: the behavior of your code is undefined.

It will be the same in C++.

pb2q
  • 58,613
  • 19
  • 146
  • 147
  • does '\0' get added explicitly or not at the end of string newStr ? – h4ck3d Sep 17 '12 at 16:30
  • it does _not_ get added explicitly. The memory at the address beyond the last character _may happen_ to contain the null character. – pb2q Sep 17 '12 at 16:33
2

I would suspect that most of the time it would keep printing past the "!" and keep going in memory until it hits a NULL. Which could result in a crash, but doesn't have to.

This is why it's best to either:

memset(newStr, 0, 30);

or

// This works because string literals guarantee a '\0' is present
// but the strlen returns everything up until the '\0'
int l = strlen(str) + 1;

this works too, but I don't feel it's as clear as adding one to strlen:

for(i =0 ; i<=l ; i ++ )

As the defination of strlen implies you need to.

Mike
  • 47,263
  • 29
  • 113
  • 177
1

By chance, most of the time the uninitialized bytes in newStr happen to be 0 in your particular case.

Graham Borland
  • 60,055
  • 21
  • 138
  • 179
1

Your program has undefined behaviour, since you promise to call printf with a pointer to a null-terminated string but fail to do so. Anything could happen, but your program is simply not correct.

Specifically, while reading the array elements one by one to find the null terminator, the program will eventually access an uninitialized variable, which is UB.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • does '\0' get added explicitly or not at the end of string newStr ? – h4ck3d Sep 17 '12 at 16:30
  • @sTEAK.: No, because `strlen` does **not** include the terminator. (The terminator is not part of the string, but only of the *implementation*.) So you need to say `strlen(str) + 1`, or use `strncpy`. – Kerrek SB Sep 17 '12 at 16:46
0

The behaviour of reading bytes that have not been initialized as characters is undefined in most implementations of C. Sometimes printf may write garbage, sometimes the program may find a null byte \0 after the last character and terminate normally. In some rare cases it may cause a crash. This is why you are seeing variation in what happens when you run the program. It depends on the compiler you are using, and what was in the memory location following that which you are allocating for the array.

(That is, if your program would compile - you've left off a semicolon)

Patrick White
  • 671
  • 5
  • 19
  • does '\0' get added explicitly or not at the end of string newStr ? – h4ck3d Sep 17 '12 at 16:32
  • @sTEAK. You need to add `'\0'` explicitly. The `for` loop you wrote only copies the non-null characters within `strlen(str)`. – timrau Sep 17 '12 at 17:26