What should be the output of this following code snippet and why?
#include <stdio.h>
#include <string.h>
int main()
{
char ch = 'A';
char str[3];
strcpy(str, "ABCDE");
printf("%c", ch);
}
The output of this program could be anything because you overrun the buffer str and get undefined behavior. In fact, the program might not output anything, it might crash, or it might do something far worse.
The snippet invokes undefined behaviour. The result can be anything, from crashing to unexpected output.
As other have mentioned, this is undefined behavior since it would depend on the contents of the memory located aftr wherever str is allocated. It will start with ABCDE but will run off into a random collection of bytes converted to chars or a crash.
The output is undefined. In linux, I am getting the output D because I think the data stored in stack from bottom to top. So, ch is stored at the bottom, and str is stored just above it. now you are overwriting str with two bytes extra, which is resulting in corrupting ch variable, which may result in displaying the D as output. Again, this depends upon compiler and operating system you are running.
Related
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Undefined, unspecified and implementation-defined behavior
This should seg fault. Why doesn't it.
#include <string.h>
#include <stdio.h>
char str1[] = "Sample string. Sample string. Sample string. Sample string. Sample string. ";
char str2[2];
int main ()
{
strcpy (str2,str1);
printf("%s\n", str2);
return 0;
}
I am using gcc version 4.4.3 with the following command:
gcc -std=c99 testString.c -o test
I also tried setting optimisation to o (-O0).
This should seg fault
There's no reason it "should" segfault. The behaviour of the code is undefined. This does not mean it necessarily has to crash.
A segmentation fault only occurs when you perform an access to memory the operating system knows you're not supposed to.
So, what's likely going on, is that the OS allocates memory in pages (which are typically around 4KiB). str2 is probably on the same page as str1, and you're not running off the end of the page, so the OS doesn't notice.
That's the thing about undefined behavior. Anything can happen. Right now, that program actually "works" on your machine. Tomorrow, str2 may be put at the end of a page, and then segfault. Or possibly, you'll overwrite something else in memory, and have completely unpredictable results.
edit: how to cause a segfault:
Two ways. One is still undefined behavior, the other is not.
int main() {
*((volatile char *)0) = 42; /* undefined behavior, but normally segfaults */
}
Or to do it in a defined way:
#include <signal.h>
int main() {
raise(SIGSEGV); /* segfault using defined behavior */
}
edit: third and fourth way to segfault
Here is a variation of the first method using strcpy:
#include <string.h>
const char src[] = "hello, world";
int main() {
strcpy(0, src); /* undefined */
}
And this variant only crashes for me with -O0:
#include <string.h>
const char src[] = "hello, world";
int main() {
char too_short[1];
strcpy(too_short, src); /* smashes stack; undefined */
}
Your program writes beyond the allocated bounds of the array, this results in Undefined Behavior.
The program is ill-formed and It might crash or may not.An explanation may or may not be possible.
It probably doesn't crash because it overwrites some memory beyond the array bounds which is not being used, bt it will once the rightful owner of that memory tries to access it.
A seg-fault is NOT guaranteed behavior.It is one possible (and sometimes likely) outcome of doing something bad.Another possible outcome is that it works by pure luck.A third possible outcome is nasal demons.
if you really want to find out what this might be corrupting i would suggest you see what follows the over-written memory generate a linker map file that should give you a fair idea but then again this all depends on how things are layed out in memory, even can try running this with gdb to reason why it does or does not segfault, that being said, the granularity for built checks in access violations (HW assisted) cannot be finer than a page unless some software magic is thrown in (even with this page granularity access checking it may happen that the immediately next page does really point to something else for the program which you are executing and that it is a Writable page), someone who knows about valgrind can explain how it is able to detect such access violations (also libefence), most likely (i might be very wrong with this explanation, Correct me if i am wrong!) it uses some form of markers or comparisons for checking if out of bounds access has happened.
I am trying to understand the array concept in string.
char a[5]="hello";
Here, array a is an character array of size 5. "hello" occupies the array index from 0 to 4. Since, we have declared the array size as 5, there is no space to store the null character at the end of the string.
So my understanding is when we try to print a, it should print until a null character is encountered. Otherwise it may also run into segmentation fault.
But, when I ran it in my system it always prints "hello" and terminates.
So can anyone clarify whether my understanding is correct. Or does it depends upon the system that we execute.
As ever so often, the answer is:
Undefined behavior is undefined.
What this means is, trying to feed this character array to a function handling strings is wrong. It's wrong because it isn't a string. A string in C is a sequence of characters that ends with a \0 character.
The C standard will tell you that this is undefined behavior. So, anything can happen. In C, you don't have runtime checks, the code just executes. If the code has undefined behavior, you have to be prepared for any effect. This includes working like you expected, just by accident.
It's very well possible that the byte following in memory after your array happens to be a \0 byte. In this case, it will look to any function processing this "string" as if you passed it a valid string. A crash is just waiting to happen on some seemingly unrelated change to the code.
You could try to add some char foo = 42; before or after the array definition, it's quite likely that you will see that in the output. But of course, there's no guarantee, because, again, undefined behavior is undefined :)
What you have done is undefined behavior. Apparently whatever compiler you used happened to initialize memory after your array to 0.
Here, array a is an character array of size 5. "hello" occupies the array index from 0 to 4. Since, we have declared the array size as 5, there is no space to store the null character at the end of the string.
So my understanding is when we try to print a, it should print until a null character is encountered.
Yes, when you use printf("%s", a), it prints characters until it hits a '\0' character (or segfaults or something else bad happens - undefined behavior). I can demonstrate that with a simple program:
#include <stdio.h>
int main()
{
char a[5] = "hello";
char b[5] = "world";
int c = 5;
printf("%s%s%d\n", a, b, c);
return 0;
}
Output:
$ ./a.out
helloworldworld5
You can see the printf function continuing to read characters after it has already read all the characters in array a. I don't know when it will stop reading characters, however.
I've slightly modified my program to demonstrate how this undefined behavior can create bad problems.
#include <stdio.h>
#include <string.h>
int main()
{
char a[5] = "hello";
char b[5] = "world";
int c = 5;
printf("%s%s%d\n", a, b, c);
char d[5];
strcpy(d, a);
printf("%s", d);
return 0;
}
Here's the result:
$ ./a.out
helloworld��world��5
*** stack smashing detected ***: <unknown> terminated
helloworldhell�p��UAborted (core dumped)
This is a classic case of stack overflow (pun intended) due to undefined behavior.
Edit:
I need to emphasize: this is UNDEFINED BEHAVIOR. What happened in this example may or may not happen to you, depending on your compiler, architecture, libraries, etc. You can make guesses to what will happen based on your understanding of different implementations of various libraries and compilers on different platforms, but you can NEVER say for certain what will happen. My example was on Ubuntu 17.10 with gcc version 7. My guess is that something very different could happen if I tried this on an embedded platform with a different compiler, but I cannot say for certain. In fact, something different could happen if I had this example inside of a larger program on the same machine.
While writing the following code I should get an error. The array size is given as zero(which I suppose is illegal) and furthermore sprintf is printing "abc" to a which has not been allocated any memory but I am getting the output as "abc". I cant understand why?
#include<stdio.h>
#include<string.h>
int main()
{
char a[0];
sprintf(a,"%s","abc");
printf("%s\n",a);
return 0;
}
I am getting the correct output when i am giving the array size to be 1,2,3 which should not be the case while it is giving segmentation fault for explicitly using a as a pointer ,i.e, using char *a(which is expected). Can somebody explain the internal working?
No, there's no reasonable explanation. By using an array which is smaller than the string to be printed, your program invokes undefined behavior. That means that literally anything can happen, including the fact that everything seems to be working fine. Undefined behavior doesn't mean that the program must crash, it means that it can crash.
So it is my understanding that a C string of, for instance "0123456789", would actually occupy an array of 11 chars, 10 chars for the body and one for the terminating null. If that is true then why does the code below NOT cause some sort of error?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char ** argv){
char * my_string = "0123456789";
/* my string should occupy 11 bytes */
int my_len = strlen(my_string);
/* however, strlen should only return 10,
because it does not count the null byte */
char * new_string = malloc(my_len);
/* allocate memory 10 bytes wide */
memcpy(new_string, my_string, my_len);
/* copy the first 10 bytes from my_string to new_string
new_string should NOT be null terminated if my understanding
is correct? */
printf("%s\n", new_string);
/* Since new_stirng is NOT null terminated it seems like this should
cause some sort of memory exception.
WHY DOES THIS NOT CAUSE AN ERROR?
*/
return 0;
}
Since new_string is not null terminated I would expect printf to just read forever until it reaches some other applications memory, or a randomly placed 0x00 somewhere and either crash or print something strange. What's going on?
You have created undefined behavior. The behavior is compiler and platform dependent. It could crash. It could work. It could make you toast. It could collapse your computer into a singularity and absorb the solar system.
In your case, it's likely that the memory at new_string[11] was already 0, which is '\0', or the terminating-null character.
Because it's undefined behavior. Undefined behavior does not mean a seg fault, although that's one possibility.
In your case, the particular memory block you got from malloc was never used before (by your program), and it was probably zero-initialized by the OS when it was allocated. Therefore, the 11th byte was likely a zero, and so no error. In a longer-running program, malloc can return a dirty chunk of memory where the 11th byte is not 0, and so you will run into problems at the printf statement. In practice, you'll either print garbage (until the first null is encountered) or segfault if there is no null before the end of the allocated region.
(As others have said, the behavior is formally undefined, I'm just explaining what you saw).
or a randomly placed 0x00 somewhere ... print something strange.
This is commonly observed behavior. What will actually happen is undefined.
This is undefined behaviour. In some cases it could cause a crash it would depend on the memory layout I would imagine
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Undefined, unspecified and implementation-defined behavior
This should seg fault. Why doesn't it.
#include <string.h>
#include <stdio.h>
char str1[] = "Sample string. Sample string. Sample string. Sample string. Sample string. ";
char str2[2];
int main ()
{
strcpy (str2,str1);
printf("%s\n", str2);
return 0;
}
I am using gcc version 4.4.3 with the following command:
gcc -std=c99 testString.c -o test
I also tried setting optimisation to o (-O0).
This should seg fault
There's no reason it "should" segfault. The behaviour of the code is undefined. This does not mean it necessarily has to crash.
A segmentation fault only occurs when you perform an access to memory the operating system knows you're not supposed to.
So, what's likely going on, is that the OS allocates memory in pages (which are typically around 4KiB). str2 is probably on the same page as str1, and you're not running off the end of the page, so the OS doesn't notice.
That's the thing about undefined behavior. Anything can happen. Right now, that program actually "works" on your machine. Tomorrow, str2 may be put at the end of a page, and then segfault. Or possibly, you'll overwrite something else in memory, and have completely unpredictable results.
edit: how to cause a segfault:
Two ways. One is still undefined behavior, the other is not.
int main() {
*((volatile char *)0) = 42; /* undefined behavior, but normally segfaults */
}
Or to do it in a defined way:
#include <signal.h>
int main() {
raise(SIGSEGV); /* segfault using defined behavior */
}
edit: third and fourth way to segfault
Here is a variation of the first method using strcpy:
#include <string.h>
const char src[] = "hello, world";
int main() {
strcpy(0, src); /* undefined */
}
And this variant only crashes for me with -O0:
#include <string.h>
const char src[] = "hello, world";
int main() {
char too_short[1];
strcpy(too_short, src); /* smashes stack; undefined */
}
Your program writes beyond the allocated bounds of the array, this results in Undefined Behavior.
The program is ill-formed and It might crash or may not.An explanation may or may not be possible.
It probably doesn't crash because it overwrites some memory beyond the array bounds which is not being used, bt it will once the rightful owner of that memory tries to access it.
A seg-fault is NOT guaranteed behavior.It is one possible (and sometimes likely) outcome of doing something bad.Another possible outcome is that it works by pure luck.A third possible outcome is nasal demons.
if you really want to find out what this might be corrupting i would suggest you see what follows the over-written memory generate a linker map file that should give you a fair idea but then again this all depends on how things are layed out in memory, even can try running this with gdb to reason why it does or does not segfault, that being said, the granularity for built checks in access violations (HW assisted) cannot be finer than a page unless some software magic is thrown in (even with this page granularity access checking it may happen that the immediately next page does really point to something else for the program which you are executing and that it is a Writable page), someone who knows about valgrind can explain how it is able to detect such access violations (also libefence), most likely (i might be very wrong with this explanation, Correct me if i am wrong!) it uses some form of markers or comparisons for checking if out of bounds access has happened.