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.
Related
I had gone to an interview in which I was asked the question:
What do you think about the following?
int i;
scanf ("%d", i);
printf ("i: %d\n", i);
I responded:
The program will compile successfully.
It will print the number incorrectly but it will run till the end
without crashing
The response that I made was wrong. I was overwhelmed.
After that they dismissed me:
The program would crash in some cases and lead to an core dump.
I could not understand why the program would crash? Could anyone explain me the reason? Any help appreciated.
When a variable is defined, the compiler allocates memory for that variable.
int i; // The compiler will allocate sizeof(int) bytes for i
i defined above is not initialized and have indeterminate value.
To write data to that memory location allocated for i, you need to specify the address of the variable. The statement
scanf("%d", &i);
will write an int data by the user to the memory location allocated for i.
If & is not placed before i, then scanf will try to write the input data to the memory location i instead of &i. Since i contains indeterminate value, there are some possibilities that it may contain a value equivalent to the value of a memory address or it may contain a value which is out of range of memory address.
In either case, the program may behave erratically and will lead to undefined behavior. In that case anything could happen.
Beacuse it invokes undefined behavior. The scanf() family of functions expect a pointer to an integer when the "%d" specifier is found. You are passing an integer which can be interpreted as the address of some integer but it's not. This doesn't have a defined behavior in the standard. It will compile indeed (will issue some warning however) but it will certainly work in an unexpected way.
In the code as is, there is yet another problem. The i variable is never initialized so it will have an indeterminate value, yet another reason for Undefined Behavior.
Note that the standard doesn't say anything about what happens when you pass a given type when some other type was expected, it's simply undefined behavior no matter what types you swap. But this particular situation falls under a special consideration because pointers can be converted to integers, though the behavior is only defined if you convert back to a pointer and if the integer type is capable of storing the value correctly. This is why it compiles, but it surely does not work correctly.
You passed data having the wrong type (int* is expected, but int is passed) to scanf(). This will lead to undefined behavior.
Anything can happen for undefined behavior. The program may crash and may not crash.
In a typical environment, I guess the program will crash when some "address" which points to a location which isn't allowed to write into by the operating system is passed to scanf(), and writing to there will have the OS terminate the application program, and it will be observed as a crash.
One thing that the other answers haven't mentioned yet is that on some platforms, sizeof (int) != sizeof (int*). If the arguments are passed in a certain way*, scanf could gobble up part of another variable, or of the return address. Changing the return address could very well lead to a security vulnerability.
* I'm no assembly language expert, so take this with a grain of salt.
I could not understand why the program would crash? Could anyone explain me the reason. Any help appreciated.
Maybe a little more applied:
int i = 123;
scanf ("%d", &i);
With the first command you allocate memory for one integer value and write 123 in this memory block. For this example let's say this memory block has the address 0x0000ffff. With the second command you read your input and scanf writes the input to memory block 0x0000ffff - because you are not accessing (dereferencing) the value of this variable i but it's address.
If you use the command scanf ("%d", i); instead you are writing the input to the memory address 123 (because that's the value stored inside this variable). Obviously that can go terribly wrong and cause a crash.
Since there is no &(ampersand) in scanf(as required by the standard), so as soon as we enter the value the program will terminate abruptly, no matter how many lines of code are written further in the program.
-->> I executed and found that in code blocks.
Same program if we run in turbo c compiler then it will run perfectly all the lines even which are after scanf, but the only thing, as we know the value of i printed would be garbage.
Conclusion:- Since at some compiler it will run and at some it would not, so this is not a valid program.
I'm new to programming. I'm attempting to run this extremely simple program as practice to integrate pointers into my code. When I run the program, it crashes on startup with a Windows has encountered an unexpected error pop-up. Absolutely no errors are given for the code itself, but the pop-up persists.
I'm running the code so far on Code::Blocks, and the program comes up with the stated pop-up from Windows on startup. I have also tested the program on codepad.org and the only error message that comes up has to do with the first line (the include statement). The error states: Segmentation fault.
#include <stdio.h>
int main() {
// Setting a variable to store the value 15.
unsigned short int random_number = 15;
// Defining my pointer.
unsigned short int *number_pointer;
// Setting the pointer to hold the memory address of my first variable.
number_pointer = random_number;
// Attempting to print the value at the memory address stored in the pointer.
printf("This code will now print a number: %i", *number_pointer);
return 0;
}
I expect the output to be: This code will now print a number: 15., however I didn't even get an output due to the program crashing.
Here
number_pointer = random_number;
number_pointer is of pointer type, and it should initialized with some valid address, not some value. In fact above statement causes compiler to warn you like
warning: incompatible integer to pointer conversion assigning to
'unsigned short *' from 'unsigned short'; take theaddress with &
[-Wint-conversion]
but you seems ignored that. Never ignore compiler warnings. Always compile code with minimal warning flags like -Wall & read those warnings. for e.g
gcc -Wall -Wextra -Wpedantic -Werror test.c
The number_pointer needs to be point to address of random_number, so that you can de-reference it like *number_pointer.
It should be
number_pointer = &random_number; /* assign the address of random_number */
The comment
// Setting the pointer to hold the memory address of my first variable.
seems correct but the commented code is not:
number_pointer = random_number;
random_number is a number, number_pointer is a pointer.
Number and pointer are different types and the compiler should warn you that they are incompatible types.
Assigning a value to a variable of an incompatible type leads to data loss (when the variable's type uses less bytes than the value's type). But the main danger when data of incompatible types is assigned is the corruption of the data.
In your case, the value of number_pointer (15, which is a number) is stored into the variable random_pointer. When the value of random_pointer is used, 15 is interpreted as a pointer, i.e. an address in memory and this is completely wrong.
The expression *number_pointer then tries to read the memory at that address and this leads to an access error that is penalized by the OS (which terminates your program).
The source of the problem is the missing & (the "address of" operator) in front of random_number in the assignment above. It should read:
number_pointer = &random_number;
This means the variable number_pointer (of type "pointer to an int") will store the address of variable random_number (of type "int"). They are compatible and the logic of the program is correct. Using the dereference operator (*) then successfully reads the integer value stored at the address stored in the number_ponter variable.
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.
int main()
{
int i,j,k;
i=1;j=2;k=3;
int *p =&k;
*(p-1)=0;
printf("%d%d%d",i,j,k);
getch();
}
the output is 1 2 3.
Your program exhibits undefined behavior, the pointer arithmetics you're doing is invalid.
You can only do pointer arithmetics on pointers that actually point into an array, and the result of the addition or subtraction must still point inside the array (or one past its end, if you don't intend to dereference it).
So anything could happen, the compiler can generate whatever code it feels like for that code.
You are not allowed to refer to p-1 after assigning it &k this is an invalid pointer for you, and the behavior of using it is undefined.
A run-time error only occurs if your stray pointer hits something that raises that error, such as some protected memory or a location that will later become a divisor in some calculation (0), for example.
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;
}