This question already has answers here:
Why does this small C program crash?
(4 answers)
Closed 9 years ago.
This code compiles with no errors under cygwin and under linux.
But when i run it, it runs with no errors in cygwin but it core-dumps under linux.
can someone shed some light about the memory management of these systems that would explain why the different behaviors?
#include <stdio.h>
void foo(char *p){
p[0]='A';
}
void main(){
char *string ="Hello world!";
foo(string);
printf("%s\n", string);
}
Thanks for the answers and makes sense that behavior is not defined, however i was interested in the differences of the underlying systems that lead to these 2 distinct undefined behaviors. I imagine its related to how they manage memory but looking for someone who is familiar with the internals who can explain why one ends up crashing while the other one does not.
In C++ string literals must not be modified. And with that pointer that's what you're trying to do.
If you want to modify it, you'll have to declare it like this:
char string[] = "Hello world!";
Modifying char* causes undefined behaviour , just because it does not crash , does not mean it won't. That is what undefined means , the behavior is not predictable , in your case , the program not crashing is also not predictable.
modification of a constant string is undefined behavior.
Also please define main() as
int main(void)
{
//your program
return 0;
}
Related
This question already has answers here:
Why doesn't my program crash when I write past the end of an array?
(9 answers)
Closed 3 years ago.
I have the following code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char buffer[2];
strcpy(buffer, "12345678910");
printf("%s\n", buffer);
return 0;
}
Since, I have already defined the char array with size 2, I shouldn't be able to put in more than 2 char plus null terminating character. Yet, it is able to take more than that without any buffer overflows or segmentation faults. Even if I copy the string strcpy(buffer, "123456789101298362936129736129369182");, it works fine. The error is generated when I push strcpy(buffer, "1234567891012983629361297361293691823691823869182632918263918");.
More of a theroetical question than a practical, but I hope it helps the new and the experienced programmers alike since it talks about the fundamentals, and helps improving coding ethics. Thanks in advance.
The simple answer is that C does not protect you from yourself. It's YOUR responsibility to check boundaries. The program will happily read and write wherever you instruct it to. However, the operating system may say something if you do this, which is usually a "segmentation fault". A worse scenario is that it may overwrite other variables.
This is a source of many bugs in C, so be careful. Whenever you're writing outside outside a buffer, you're invoking undefined behavior and these can manifest themselves in various ways, including the program working as it should, overwriting variables and segmentation faults.
I shouldn't be able to put in more than 2 char plus null terminating character
This is a common bug. It's NOT "plus null terminating character". It's INCLUDING null terminating character.
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.
This question already has answers here:
Does "Undefined Behavior" really permit *anything* to happen? [duplicate]
(9 answers)
Closed 6 years ago.
I have one incredible segment crash call stack in C, could anyone help me out?
int function(struct A *a)
{
... some other declare
struct B *b = a->b;
int count, len;
... some other declare
struct C *c = b->c; /* not crash here */
....some other decalre
if (b->e) { /*crash log indicate b is NULL and crash here,first line instrucment code*/
.....
}
....
}
My question is why the crash did not happened at the struct C *c = b->c.
GCC is the compiler.
Tony
The compiler does not guarantee ordered execution of instructions unless there is a data flow dependency. It has numerous optimizations, one of which is data flow optimization.
Also, if you don't use the variable c at all, the compiler will optimize it out of the code (dead code optimization) and you may not see a crash at all (if the rest of the program works fine).
One easy way to understand which optimization is happening is to access the c variable somewhere. Another way is to disable optimizations (-O0 in GCC).
This question already has answers here:
I want this to crash, but it doesn't
(4 answers)
Closed 7 years ago.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *a[10];
a[2] = (int*)malloc(sizeof(int));
a[2][3]=4;
printf("%d", a[2][3]);
return 0;
}
I have given only the memory equivalent of a single int to the pointer variable. How is that I am able to access an element at index 3 for that pointer of a single int?
That's because nothing is preventing you accessing arrays out of bound and this invokes undefined behavior. Any expected or unexpected behavior of program can be seen.
You can try but the behaviour of your program will be undefined.
C does not perform that kind of checking at runtime.
You're accessing some randomly set RAM element. This is a common C programming mistake and is one of the reason for many security flaws.
The Heartbleed bug would be a nice example, where people were able to read a good portion of the server RAM, by accessing elements outside of the array structure.
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.