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).
Related
This question already has answers here:
Allocating memory for a part of structure
(2 answers)
Closed 2 years ago.
I recently came across some code that uses a "cool hack" like the following:
#include <stddef.h>
#include <stdlib.h>
struct foo {
int a;
char *b;
int optional;
char huge[5000];
/* lots more members */
};
void myfunc(void) {
struct foo *p;
p = malloc(offsetof(struct foo, optional));
if (p) {
p->a = 17;
p->b = "Hello";
/* do stuff with p->a and p->b */
free(p);
}
}
The idea is to "save memory" by only allocating the part of struct foo that is actually going to be used.
I see many obvious reasons why this code is a bad idea: it will certainly break if you reorder the members of struct foo, or if you forget which members you're allowed to use, or if you accidentally assign *p or pass it to a function by value. (And in the code linked, it saves a whopping 80 bytes per call, for a function that most programs will only call a handful of times.)
But is it actually undefined behavior or otherwise illegal with respect to the C standard? If so, are there examples of real-life implementations where it won't work as intended?
I don't think the Standard made any effort to consider this pattern. It was certainly in common use when the Standard was written, and supported by all commonplace implementations. While there was no obvious reason why any general-purpose implementations wouldn't support it, I don't know that the authors of the Standard wanted to preclude the possibility of implementations whose customers wouldn't need this pattern, squawking if they noticed allocations' addresses assigned to pointer-to-structure types that were too big for them. Instead, I think they expected implementations to process such constructs usefully absent a good reason to do otherwise, but didn't want to speculate what "good reasons" might be.
As to the question of whether such code will work reliably, there's no particular reason why it shouldn't, and I don't know of any particular situations where it would cause problems with clang or gcc, but present or future versions might find some "clever" optimizations where it would fail.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
It's an exercise of my college. The goal is to make illegal memory store and illegal memory access and print it in char. However, using MALLOC has memory adresses doesn't store 'y', and using char x works. Why this difference? But when I use char x it shows me what I want, however, in the end show me this text "* stack smashing detected *: terminated
Abortado (imagem do nĂșcleo gravada)"
void ilegal_store(char *u)
{
for(int i=0;i<100;i++){
*(u+i) = 'y';
}
}
void ilegal_reading(char *u)
{
for(int i=0;i<100;i++){
printf("%d = %d\n",i,*(u+i));
}
}
void main()
{
//char x; WORKS
char *x=(char *)malloc(sizeof(char)); //USING MALLOC HAS ADRESSES WHICH DOESN'T STORE THE 'y' by ilegal_store();
if(x!=NULL){
ilegal_store(x); //use &x when not pointer
ilegal_reading(x); //use &x when not pointer
}
}
The C standard does not permit you to dereference a pointer to memory that you don't own. The behaviour on attempting to do so is undefined. Undefined behaviour manifests itself in many curiosities such as "working" sometimes, not "working" sometimes, or the compiler even erasing that particular branch: it's allowed to assume that undefined behaviour does not occur.
It's possible that you will not get a crash at exactly the first undefined dereference. Because the output of printf is frequently buffered and therefore often in lag of the code generating the output, you might be able to produce a extra output for the uncommented case by flushing the buffer after every iteration using fflush(stdout). The presence of the newline character in the case you cite as working can also flush the buffer. It's probably the newline character that is producing the different behaviour.
Finally, however this is dressed up, you are circumventing contraints the language places on you. If you want to circumvent these constraints then you need to use a different language. Many C compilers support inline assembly. That's what you need to use in this instance.
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:
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;
}
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
memcpy vs assignment in C
I wanted to know if there is a gain in performance of assigning a big structure (e.g 100 bytes) automatic variable to zero rather than doing memset it to zero in run time in C.
Not sure if gcc compiler can do optimization at compile time for this
Below are the two cases
Case 1:
void fun1()
{
struct S y = {0};
}
Case 2:
void fun1()
{
struct S y;
memset(&y, 0, sizeof(y));
}
gcc will almost certainly handle this better than you can, and this is probably not a bottleneck in your system performance, so you shouldn't worry about trying to optimize this.
This is almost an exact duplicate of memcpy vs assignment in C
Assignment is almost always better than direct memory manipulation (not to mention more verbose). And code is, after all, meant to be read; not just written.