i have a problem with this function this function using a pointer without referencing it but I surprised that it working and I don't know why ptr in the Function is not referenced and function working without error if any person can explain me why it not generate error i'll be so grateful
#include<stdio.h>
int * Ret(int *x)
{
int *ptr;
*ptr = (-1*(*x));
return ptr;
}
int main(void)
{
int val = 5,op;
op = *Ret(&val);
printf("%d",op);
}
output will be -5 but I think that it must generate run time error ?
It's undefined behaviour.
Anything can happen and because of that can be a valid behaviour.
If you want to catch these problems use external tools, e.g. valgrind or a custom compiler e.g. clang with address sanitizer.
You are right in the fact that the function is doing something wrong.
The function returns a pointer to an integer which is allocated only inside the function.
The memory (the value) the pointer points to does not change at the end of the function and this is why you get the correct value. (the implementation of C allows it)
if you had more function later on, they might have override this memory and the value of 'op' might have changed
Bottom line, don't do it!
int *ptr is on the stack. Stack variables are not initialized. So it can have any value. The *ptr= assignment dereferences ptr, that is, the "any value" is taken as an address and the right hand side is stored there. If "any value", as an address, is outside the program's assigned memory, a run time error will ocur. Otherwise some memory of the program is overwritten; this error can become manifest at any later moment, can not manifest itself at all, or can give (noted or unnoted) wrong results. "Bad code", in summary.
The compiler could catch the error by flagging the use of ptr as use of an uninitialized variable.
Related
Consider the following code.
#include<stdio.h>
int *abc(); // this function returns a pointer of type int
int main()
{
int *ptr;
ptr = abc();
printf("%d", *ptr);
return 0;
}
int *abc()
{
int i = 45500, *p;
p = &i;
return p;
}
Output:
45500
I know according to link this type of behavior is undefined. But why i am getting correct value everytime i run the program.
Every time you call abc it "marks" a region at the top of the stack as the place where it will write all of its local variables. It does that by moving the pointer that indicates where the top of stack is. That region is called the stack frame. When the function returns, it indicates that it does not want to use that region anymore by moving the stack pointer to where it was originally. As a result, if you call other functions afterwards, they will reuse that region of the stack for their own purposes. But in your case, you haven't called any other functions yet. So that region of the stack is left in the same state.
All the above explain the behavior of your code. It is not necessary that all C compilers implement functions that way and therefore you should not rely on that behavior.
Well, undefined behavior is, undefined. You can never rely on UB (or on an output of a program invoking UB).
Maybe, just maybe in your environment and for your code, the memory location allocated for the local variable is not reclaimed by the OS and still accessible, but there's no guarantee that it will have the same behavior for any other platform.
I would like to understand the difference between the following two C programs.
First program:
void main()
{
int *a;
{
int b = 10;
a=&b;
}
printf("%d\n", *a);
}
Second program:
void main()
{
int *a;
a = foo();
printf("%d\n", *a);
}
int* foo()
{
int b = 10;
return &b;
}
In both cases, the address of a local variable (b) is returned to and assigned to a. I know that the memory a is pointing should not be accessed when b goes out of scope. However, when compiling the above two programs, I receive the following warning for the second program only:
warning C4172: returning address of local variable or temporary
Why do I not get a similar warning for the first program?
As you already know that b goes out of scope in each instance, and accessing that memory is illegal, I am only dumping my thoughts on why only one case throws the warning and other doesn't.
In the second case, you're returning the address of a variable stored on Stack memory. Thus, the compiler detects the issue and warns you about it.
The first case, however skips the compiler checking because the compiler sees that a valid initialized address is assigned to a. The compilers depends in many cases on the intellect of the coder.
Similar examples for depicting your first case could be,
char temp[3] ;
strcpy( temp, "abc" ) ;
The compiler sees that the temp have a memory space but it depends on the coder intellect on how many chars, they are going to copy in that memory region.
your foo() function has undefined behavior since it returns a pointer to a part of stack memory that is not used anymore and that will be overwritten soon on next function call or something
it is called "b is gone out of scope".
Sure the memory still exists and probably have not changed so far but this is not guaranteed.
The same applies to your first code since also the scope of b ends with the closing bracket of the block there b is declared.
Edit:
you did not get the warning in first code because you did not return anything. The warning explicitly refers to return. And since the compiler may allocate the stack space of the complete function at once and including all sub-blocks it may guarantee that the value will not be overwritten. but nevertheless it is undefined behavior.
may be you get additional warnings if you use a higher warning level.
In the first code snippet even though you explicitly add brackets the stack space you are using is in the same region; there are no jumps or returns in the code so the code still uses consecutive memory addresses from the stack. Several things happen:
The compiler will not push additional variables on the stack even if you take out the code block.
You are only restricting the visibility of variable b to that code-block; which is more or less the same as if you would declare it at the beginning and only use it once in the exact same place, but without the { ... }
The value for b is most likely saved in a register which so there would be no problem to print it later - but this is speculative.
For the second code snippet, the function call means a jump and a return which means:
pushing the current stack pointer and the context on the stack
push the relevant values for the function call on the stack
jump to the function code
execute the function code
restore the stack pointer to it's value before the function call
Because the stack pointer has been restored, anything that is on the stack is not lost (yet) but any operations on the stack will be likely to override those values.
I think it is easy to see why you get the warning in only one case and what the expected behavior can be...
Maybe it is related with the implementation of a compiler. In the second program,the compiler can identify that return call is a warning because the program return a variable out of scope. I think it is easy to identify using information about ebp register. But in the first program our compiler needs to do more work for achieving it.
Your both programs invoke undefined behaviour. Statements grouped together within curly braces is called a block or a compound statement. Any variable defined in a block has scope in that block only. Once you go out of the block scope, that variable ceases to exist and it is illegal to access it.
int main(void) {
int *a;
{ // block scope starts
int b = 10; // b exists in this block only
a = &b;
} // block scope ends
// *a dereferences memory which is no longer in scope
// this invokes undefined behaviour
printf("%d\n", *a);
}
Likewise, the automatic variables defined in a function have function scope. Once the function returns, the variables which are allocated on the stack are no longer accessible. That explains the warning you get for your second program. If you want to return a variable from a function, then you should allocate it dynamically.
int main(void) {
int *a;
a = foo();
printf("%d\n", *a);
}
int *foo(void) {
int b = 10; // local variable
// returning the address of b which no longer exists
// after the function foo returns
return &b;
}
Also, the signature of main should be one of the following -
int main(void);
int main(int argc, char *argv[]);
In your first program-
The variable b is a block level variable and the visibility is inside that block
only.
But the lifetime of b is lifetime of the function so it lives upto the exit of main function.
Since the b is still allocated space, *a prints the value stored in b ,since a points b.
I've done the following:
char * copyact(char * from)
{
return ++from;
}
int main()
{
char *string = "school";
char *copy;
copy = copyact(string);
printf("%s", copy);
}
This is printing chool, however my idea is the application must crash when we try to print it in main(). By scope rules, parameter from is a variable local to copyact function. I'm doing from = from + 1; and returning address to that place. So when we get back to main, shouldn't the memory given to that location now be invalid because all local variables must be destroyed? Why is this thing still working?
Clarification: Don't we assign a memory location for the pointer &from in which it stores the address for the string? When the function exits, don't we also destroy the address of pointer that holds the valid address? or is it because by the time return is executed, the address it points to was already sent to copy= ?
1. Undefined behavior is not a crash
First of all please remember that when you do bad things with memory (like handling a variable after it has been destroyed) the result is undefined behavior and this means something completely different from a "crash".
Undefined behavior means that anything can happen (including a crash) but anything may also mean "nothing". Actually the worst kinds of bug are those in which undefined behavior doesn't do anything apparent immediately, but only to provoke crazy behavior in some other and unrelated and innocent part of the code one million of instructions executed later. Or only when showing your program in front of a vast audience.
So please remember that undefined behavior is not crash. It's a crash only when you're lucky.
The sooner you understand the difference between a bug and a crash and the better it is. Bugs are your enemies, crashes are your friends (because they reveal a bug).
2. This code is not doing anything bad
The function returns a char *, and this value (a pointer) is computed by pre-incrementing a local variable. When the function returns the local variable is destroyed, but because the function was returning its value (a pointer) then the code is perfectly safe.
It would have been unsafe instead if the function was defined as
char *& copyact(char * from)
{
return ++from;
}
because in this case the return value is a reference to a pointer to char and it would have returned a reference to from that was however going to be already destroyed by the time the caller could access the returned reference.
By the way for exampe g++ compiler emits a warning when you compile the modified version:
vref.cpp: In function ‘char*& copyact(char*)’:
vref.cpp:3:9: warning: reference to local variable ‘from’ returned
Note however that even in this case you cannot expect that running the code would generate a crash for sure. For example on my computer running the buggy code with the modified version just prints "school" instead of "chool".
It doesn't make much sense, but this is quite normal once you enter Undefined Behavior realm.
It works, because your function gets the reference to the object that already exists outside of it. The result it returns is just a value. Though judging by the code, it returns the pointer to the string shifted by one from start. I am not sure that was the idea, also it will probably crash if the original was an empty string.
char * copyact(char * from)
{
return ++from;
}
char *string = "school";
char *copy;
copy = copyact(string);
You are making farm points to "school" , which is already there in memory
and you are returned from+1 that points to "chool"
For example in which case you should not return.
char * copyact(char * from)
{
char a[10]; //declared array, has automatic scope.
return a; // you should not return a and can't be accessed outside of function.
}
With MinGW 4.6.2 (4.7.x does not seem to be the "latest" on sourceforge, so this one got installed)
void test(int *in)
{
*in = 0;
}
int main()
{
int dat;
test(dat);
return dat;
}
As you are probably aware this will give a warning in a c project.
dirpath\fileName.c|8|warning: passing argument 1 of 'test' makes pointer from integer without a cast [enabled by default]
And 2 errors in a c++ project.
dirpath\fileName.cpp|8|error: invalid conversion from 'int' to 'int*' [-fpermissive]|
dirpath\fileName.cpp|1|error: initializing argument 1 of 'void test(int*)' [-fpermissive]|
My question is, what exactly happens (in memory) during the two following scenarios, assume -fpermissive is enabled or compiled as a c program.
dat is uninitialized and the program proceeds (and no segmentation fault occurs).
dat is initialized to 42, and the program proceeds (and does seg-fault).
Why does leaving dat uninitialized lead to no seg-fault (perhaps by chance?) while case 2 causes a seg-fault (perhaps attempting to assign a value to a memory location)?
Curiosity: what does the f stand for in -fpermissive, flag perhaps? (seems redundant)
The program has undefined behavior as-is, so it's pointless to try to reason its behavior, but anyway...
The test() function expects a pointer to int. That pointer will be dereferenced and used to set the int it points to. However, you don't pass it a pointer to int but an uninitialized int - so it will try to interpret whatever garbage value is in that variable as a memory address and then access the object behind it - and boom.
If you wanted to call the function correctly, you would need to write
test(&dat);
instead.
what does the f stand for in -fpermissive, flag perhaps?
No, as far as I know, it stands for "feature". (But in the case of -fpermissive, I'd say it stands for "your code is f..ked if you use this flag"...)
As Warning says passing argument 1 of 'test' makes pointer from integer, you are trying to fetch something from a address which is value of passed integer.It may be anything.
when you are passing value 42, compiler is getting forced to fetch some value at address 42 which is not reserved for user and you are getting Segfault.By default compiler is assigning some value and later this values is becoming address, and somehow you are lucky that you do not get Segment fault with this.
In c by default pass by value takes place.
void test(int *in)
{
*in = 0;
}
test(dat); // passing value
here you are passing dat which is uninitialized. It will consider a garbage value. So you are trying to make the garabage value to act as a memory address in the test function. It is undefined behaviour. Instead you can try this.
test(&data);
Coming to your question.
Q. dat is uninitialized and the program proceeds (and no segmentation fault occurs).
A. This is an undefined behaviour because your are passing a garbage value. If your
garbage value is a proper memory address then it will not cause segmentation error.
If it is not proper, it will cause segmentaion error. So it happend at runtime
dynamically and can give either segmentation fault or can run.
Q. dat is initialized to 42, and the program proceeds (and does seg-fault)
A. Here you have initialized dat to 42. By default c works on pass by value definition.
So you are passing 42 to test. test will consider 42 as a memory location, which
is not a proper memory location so it cause segmentation error.
This is a simple piece of code which i wrote to check whether it is legitimate to return the address of a local variable and my assumptions were proved correct by the compiler which gives a warning saying the same:
warning: function returns address of local variable
But the correct address is printed when executed... Seems strange!
#include<stdio.h>
char * returnAddress();
main()
{
char *ptr;
ptr = returnAddress();
printf("%p\n",ptr);
}
char * returnAddress()
{
int x;
printf("%p\n",&x);
return &x;
}
The behaviour is undefined.
Anything is allowed to happen when you invoke undefined behaviour - including behaving semi-sanely.
The address of a local variable is returned. It remains an address; it might even be a valid address if you're lucky. What you get if you access the data that it points to is anyone's guess - though you're best off not knowing. If you call another function, the space pointed at could be overwritten by new data.
You should be getting warnings about the conversion between int pointer and char pointer - as well as warnings about returning the address of a local variable.
What you are trying to do is usually dangerous:
In returnAddress() you declare a local, non-static variable i on the stack. Then you return its address which will be invalid once the function returned.
Additionally you try to return a char * while you actually have an int *.
To get rid of the warning caused by returning a pointer to a local var, you could use this code:
void *p = &x;
return p;
Of course printing it is completely harmless but dereferencing (e.g. int x = *ptr;) it would likely crash your program.
However, what you are doing is a great way to break things - other people might not know that you return an invalid pointer that must never be dereferenced.
Yes, the same address is printed both times. Except that, when the address is printed in main(), it no longer points to any valid memory address. (The variable x was created in the stack frame of returnAddress(), which was scrapped when the function returned.)
That's why the warning is generated: Because you now have an address that you must not use.
Because you can access the memory of the local variable, doesn't mean it is a correct thing to do. After the end of a function call, the stack pointer backtracks to its previous position in memory, so you could access the local variables of the function, as they are not erased. But there is no guaranty that such a thing won't fail (like a segmentation fault), or that you won't read garbages.
Which warning? I get a type error (you're returning an int* but the type says char*) and a warning about returning the address of a local variable.
The type error is because the type you've declared for the function is lies (or statistics?).
The second is because that is a crazy thing to do. That address is going to be smack in the middle (or rather, near the top) of the stack. If you use it you'll be stomping on data (or have your data stomped on by subsequent function calls).
Its not strange. The local variables of a function is allocated in the stack of that function. Once the control goes out of the function, the local variables are invalid. You may have the reference to the address but the same space of memory can be replaced by some other values. This is why the behavior is undefined. If you want reference a memory throughout your program, allocate using malloc. This will allocate the memory in heap instead of stack. You can safely reference it until you free the memory explicitly.
#include<stdio.h>
#include<stdlib.h>
char * returnAddress();
main()
{
char *ptr;
ptr = returnAddress();
printf("%p\n",ptr);
}
char * returnAddress()
{
char *x = malloc(sizeof(char));
printf("%p\n",x);
return x;
}