So I am working on the exercise below, and I understand the problems related to dereferencing null pointer as in the code below.
Swap.c
int main () {
int a = 1, b = 2;
swap(&a, &b);
}
void swap (int *px, int *py) {
int *temp;
*temp = *px; //Crashes here
*px = *py;
*py = *temp;
}
Now my issues is on my pc I always get sigsegv if proc exists or not. I assume this is windows not allowing memory access violations.This makes it impossible to really do the exercise below. Does this behave differently on a native Linux machine? Suggestions?
(Exercise) Create swap.c
Supply the definition of a C procedure proc to be called in the main
program immediately prior to the call to the buggy swap (swap2.s) that
will guarantee that swap will crash when the uninitialized temp pointer is
dereferenced (it should cause a crash on *temp). Also explain why your
call guarantees this crash. Hint: your proc procedure will leave
something on the stack.
int main () {
int a = 1, b = 2;
proc(/* Some args might go here */);
swap(&a, &b);
}
Q2. Explain how you guarantee it crashing with what is in proc.
But this is tricky when it always crashes at the deref.?
Related
I am trying to get deep acknowledge of pointers. while I am running this example it doesn't output any thing due to segmentation fault. But when I am trying to run the code line by line from GDB it works normally
Look at screen shot.
#include <stdio.h>
struct s{
int a;
struct s* next;
};
struct s foo() {
struct s m ;
struct s f[10];
m.a = 55;
m.next =&(f[0]);
int i = 0;
while(i < 9) {
f[i].a = 28 + i;
f[i].next = &(f[i+1]);
i++;
}
return f[0];
}
int main()
{
struct s f = (foo());
printf("%d ",f.a);
printf("%d ",f.next->a);
printf("%d ",f.next->next->a);
return 0;
}
if you change the main function to be like this :
int main(){
struct s f = (foo()); int a = f.a;
int b - f.next->a;
int c = f.next->next->a;
int d = f.next->next->next->a;
int g = f.next->next->next->next->a;
printf("%d %d %d %d %d\n", a, b , c ,d, g);
}
it will work fine.
this screen shot is n't working when I am trying to call printf directly .
this is working when I am trying to store in variables first and then call printf on the variables
]
In C, variables that are defined inside a function are either static or automatic (auto). The default is automatic. The lifetime of automatic variables ends when the function returns and its return value has been copied to another variable or used in an expression.
struct s foo() {
struct s f[10];
int i = 0;
while(i < 9) {
f[i].a = 28 + i;
f[i].next = &(f[i+1]);
i++;
}
return f[0];
}
int main()
{
struct s f = (foo())
So after foo's return value has been stored in main's f, foo's f array is no longer alive, and trying to access any part of it is an error.
So why does the following work?
int b = f.next->a;
int c = f.next->next->a;
int d = f.next->next->next->a;
int g = f.next->next->next->next->a;
printf("%d %d %d %d %d\n", a, b , c ,d, g);
The reason is that your implementation of C stores automatic variables in a stack, and doesn't shrink the stack after a function finishes. Instead, the variables remain undisturbed until another function is called. That function will reuse all or part of the stack space, overwriting variables without regard to their old types. A pointer may be overwritten by an integer, or a few character of a string, or something else.
So, although it's undefined behavior and you should never rely on this working, you can access parts of the f array in this particular case because no function has been called since foo returned.
Similarly, in your GDB session, since you've stopped your program after foo returns but before printf has been called, GDB can safely access f.next->next->a, etc., but it's still undefined behavior.
Your second version does call functions, and that's when you're going to run into trouble.
printf("%d ",f.a);
printf("%d ",f.next->a);
printf("%d ",f.next->next->a);
The first line, printf("%d ",f.a), will work fine. main's f is valid. But the call to printf is going to overwrite the stack previously used by foo, including all or part of what used to be foo's f array.
Note that you won't see this output yet, because printf won't print out anything until you've asked it to print the end-of-line character.
The next line, printf("%d ",f.next->a);, is going to print a seemingly random integer, because foo's f[1].a has been overwritten with whatever local variables printf uses. And, again, you won't see any output yet because of buffering.
The next line, printf("%d ",f.next->next->a), is where things come crashing down. foo's f[1].next is almost certainly not going to be a valid pointer, so you get a segmentation fault.
How can you make this work correctly? If you want foo's f array to stay alive for the entire duration of the program, just prefix the declaration with the keyword static. That means there will be one copy of the f array, no matter how many times you call foo. If you want each call to foo to allocate a new f array, you can use the malloc function. Space allocated by malloc will remain alive until either you call free or the program exits.
When I compile this code :
int main() {
int a = 10;
int *p = &a;
printf("%p",p) // or printf("%p",&a);
return 0;
}
it prints 0022ff38.
Then this code :
int a=10;
int *p =(int *)0x22ff38;
printf("%d",*p); //does not output 10;
should print 10, but it output another thing(2293560).
But when I edit the code, and add a single line :
int main() {
int a = 10;
int *p =(int *)0x22ff38;
printf("%p",&a);
printf("%d",*p); // Now it prints correctly:10
return 0;
}
Every thing is ok!.
Questions:
Why my code does not output a value in first code?
What is usage of this way addressing pointers? is it useful?
Edit :
I have no problem in Linux, because in Linux every time that I run the code, the variable address changes and program output segmentation fault. but in windows address remains the same, and it is expected that manual addressing work in windows.
Compilers are smarter than you think. For example, given this code:
int main() {
int a=10;
int *p =(int *)0x22ff38;
printf("%d",*p);
}
The compiler is going to see that a is never even used. So it will never bother to actually allocate any memory for it.
If you add a printf("%d", a), the compiler might only put a in a register and never in memory.
Fundamentally, you can't assume that two programs will put variables in the same place in memory.
I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting. So according to me answer should be option A. But in official GATE-2017 exam answer key, answer is given D. So am i wrong ? how ?
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int *assignval(int *x, int val){
*x = val;
return x;
}
void main(){
clrscr();
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
x = (int *)malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,10);
}
printf("%d\n",*x);
free(x);
getch();
}
(A) compiler error as the return of malloc is not typecast
appropriately.
(B) compiler error because the comparison should be made as x==NULL
and not as shown.
(C) compiles successfully but execution may result in dangling
pointer.
(D) compiles successfully but execution may result in memory leak.
In my opinion option D is only correct when int *x = (int *)malloc(sizeof(int)); is used.
There's no right answer among the choices offered.
The immediately obvious problems with the code, under assumption that the code is supposed to be written in standard C:
Standard library does not have <conio.h> header or <iostream.h> header.
void main() is illegal. Should be int main(). Even better int main(void)
clrscr(), getch() - standard library knows no such functions.
The second malloc leaks memory allocated by the first one (assuming the first one succeeds).
Result of second malloc is explicitly cast - bad and unnecessary practice.
The statement :
int *x = malloc(sizeof(int));
will not lead to compile error, as it declares x as a pointer to int and initializes it right afterwards. It did not have type void beforehand.
The statement :
x = (int *)malloc(sizeof(int));
causes a possible memory leak, as it reallocates the memory which is already allocated for x.
NOTE : However none of this answers is completely correct. This code will not compile for various reasons.
If this is your code, change :
void main()
to :
int main(void)
and also see why you should not cast the result of malloc.
Apart from that, clrscr(), getch(), <conio.h> and <iostream.h> are not recognized by standard library.
I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting.
There's more than a little debate about whether or not to cast malloc, but it's a stylistic thing. void * is safely promoted to any other pointer.
ISO C 6.3.2.3 says...
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Whatever you choose, pick one and stick with it.
The memory leak is here:
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
// Memory leak
x = (int *)malloc(sizeof(int));
The first malloc points x at allocated memory. The second malloc can only happen if the first succeeded (if x is true). The pointer to the memory allocated by the first malloc is lost.
Using a new variable would fix the leak, keeping in mind that the code is nonsense.
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
int *y = malloc(sizeof(int));
if(NULL==y) return;
y = assignval(y,10);
free(y);
}
As a side note, void main() is technically not a violation of the ISO C standard, it is "some other implementation-defined manner".
5.1.2.2.1 says:
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
int main(int argc, char argv[]) { / ... */ }
or equivalent;) or in some other implementation-defined manner.
I'm guessing you're using a Windows compiler, that would be the "some other implementation". clang considers it an error.
test.c:8:1: error: 'main' must return 'int'
void main(){
^~~~
int
1 error generated.
you should never forget that a void * pointer can be assigned to all type of pointers. in IDEs like visual studio, you get a compile error if you do not perform casting while assigning a void * to <>. for example:
float *ptr = malloc(sizeof(float));//compile error in visual studio.
but if you compile it with GCC without typecasting, you won't get a compile error.
#include <stdio.h>
void interrupt();
int main() {
int n = 8;
char c = 'Z';
interrupt();
printf("%d%c\n", n, c);
}
void interrupt() {
printf("Run normally\n");
//ADD CODE...
}
As it stands, this function will output "8Z" regardless of what the interrupt() method does. I am attempting to modify it such that it prints "3Y" without changing anything in the original main function, and only using the interrupt() function (not allowed to pass arguments!). I am allowed to use variables in the interrupt() function, but I am confused to as how you obtain the addresses of 'n' and 'c' without making a global variable, which would defeat the purpose of this question. Since the address of the stack changes every time this runs, there doesn't seem to be a way to do pointer arithmetic (which is what I need to do), and therefore I'm a bit confused and stuck.
Disclaimer: Don't attempt to use this in production code
I took this as a puzzle and proceeded to solve it. You said you are not allowed to modify main. I took the liberty of modifying main slightly -- to print the addresses of n and c.
int main()
{
int n = 8;
char c = 'Z';
printf("%p %p\n", &n, &c);
interrupt();
printf("%d%c\n", n, c);
}
I also modified interrupt a little bit, also to print the values of an address.
void interrupt() {
int i = 10;
char* np = (char*)&i;
char* cp = (char*)&i;
printf("%p %p\n", np, cp);
printf("%p\n", &i);
}
When I ran the program, I got the following output:
0x22cb0c 0x22cb0b
0x22cabc 0x22cabc
0x22cabc
8Z
From the output, I am able to compute the offset between &n in main and &i in interrupt, and the offset between &c in main and &i in interrupt. Now I can manipulate the offset to make np and cp in interrupt to point to n and c in main.
void interrupt() {
int i = 10;
char* np = (char*)&i;
char* cp = (char*)&i;
np += (0x22cb0c - 0x22cabc);
cp += (0x22cb0b - 0x22cabc);
*(int*)np = 3;
*cp = 'Y';
printf("%p %p\n", np, cp);
printf("%p\n", &i);
}
With the changes to interrupt, I get the following output:
0x22cb0c 0x22cb0b
0x22cb0c 0x22cb0b
0x22cabc
3Y
Mission accomplished by changing main a little bit. If you are not allowed to change it at all, you'll have to use a different program to compute the offsets.
By what #Alex Skalozub said, you can get the stack offset and modify the local variables in the calling function.
You can:
1. Study the compiler and OS manual to calculate the stack offset.
Or
2. Write a little function to get it at run-time. Like below.
int get_stack_offset(void)
{
long dummy1;
return dummy_call(&dummy1) + sizeof(dummy1);
}
int dummy_call(int address)
{
long dummy2;
return &dummy2 - address;
}
Then you can just
void interrupt() {
printf("Run normally\n");
int stack_offset = get_stack_offset();
char* c_address = (char*) (&stack_offset - stack_offset);
int* n_address = (int*) (c_address - sizeof(char));
// Then, modify them
*c_address = 'Y';
*n_address = 3;
// Other
// ...
}
*Assuming the stack is increasing. When it is decreasing you need reverse the +/- operator.
*I don't consider about alignment, which maybe you need to.
*And here is a great explanation you can reference.
Does stack grow upward or downward?
I have a piece of code where I am trying to return the square of the value pointed to by *ptr.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
main()
{
int a=8,t;
t=square(&a);
printf("%d",t);
}
Its working fine for me but author of this code said it might not work because of following reason:
Because it's possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square!. The correct way to do is
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
I really wanted to know why he said like that?
The idea of the volatile keyword is exactly to indicate to the compiler that a variable marked as such can change in unexpected ways during the program execution.
However, that does not make it a source of "random numbers" - it just advises the compiler - what is responsible for actually changing the variable contents should be another process, thread, some hardware interrupt - anything that would write to the process memory but not inlined in the function where the volatile declaration finds itself. In "older times" (compilers with less magic) everything it did was preventing the compiler from caching the variable value in one of the CPU registers. I have no idea on the optimisations/de-optimistions strategies triggered by it by modern compilers - but it will at least do that.
In the absense of any such external factor, a "volatile" variable is just like any other. Actually - it is just like any other variable - as variables not marked as volatile can also be changed by the same external causes (but the compiled C code would not be prepared for that in this case, which might lead to incorrect values being used).
Since the question has an accepted and correct answer, I will be brief: here is a short program that you can run to see the incorrect behavior happening for yourself.
#include <pthread.h>
#include <math.h>
#include <stdio.h>
int square(volatile int *p) {
int a = *p;
int b = *p;
return a*b;
}
volatile int done;
void* call_square(void* ptr) {
int *p = (int*)ptr;
int i = 0;
while (++i != 2000000000) {
int res = square(p);
int root = sqrt(res);
if (root*root != res) {
printf("square() returned %d after %d successful calls\n", res, i);
break;
}
}
done = 1;
}
int main() {
pthread_t thread;
int num = 0, i = 0;
done = 0;
int ret = pthread_create(&thread, NULL, call_square, (void*)&num);
while (!done) {
num = i++;
i %= 100;
}
return 0;
}
The main() function spawns a thread, and modifies the data being squared in a loop concurrently with another loop calling the square with a volatile pointer. Relatively speaking, it does not fail often, but it does so very reliably in less than a second:
square() returned 1353 after 5705 successful calls <<== 1353 = 33*41
square() returned 340 after 314 successful calls <<== 340 = 17*20
square() returned 1023 after 5566 successful calls <<== 1023 = 31*33
First understand what's volatile: Why is volatile needed in C?
and then, try to find answer by yourself.
It's a game of volatile and hardware world. :-)
Read answer given by Chris Jester-Young:
volatile tells the compiler that your variable may be changed by other means, than the code that is accessing it. e.g., it may be a I/O-mapped memory location. If this is not specified in such cases, some variable accesses can be optimised, e.g., its contents can be held in a register, and the memory location not read back in again.
If there is more than one thread, the value the pointer points to might change inbetween statement "a = *ptr" and statement "b = *ptr". Also: you want the square of a value, why put it into two variables?
In the code you present then there is no way for the variable a that is defined in your main to be modified whilst square is running.
However, consider a multi-threaded program. Suppose that another thread modified the value to your your pointer refers. And suppose that this modification took place after you had assigned a, but before you had assigned b, in the function sqaure.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//the other thread writes to *ptr now
b = *ptr;
return a * b;
}
In this scenario, a and b would have different values.
The author is correct (if *ptr will be changed by other threads)
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//between this two assignments *ptr can change. So it is dangerous to do so. His way is safer
b = *ptr;
return a * b;
}
Because the value of the pointer *ptr might change between the first affection and the second one.
I don't think the value of *ptr can change in this code barring an extremely unusual (and non-standards-compliant) runtime environment.
We're looking at the entirety of main() here and it's not starting up other threads. The variable a, whose address we are taking, is a local in main(), and main() doesn't inform any other function of that variable's address.
If you added the line mysterious_external_function(&a); before the t=square(&a) line, then yes, mysterious_external_function could start a thread and diddle the a variable asynchronously. But there's no such line, so as written square() always returns a square.
(Was the OP a troll post, by the way?)
I see some answers with *ptr can be changed by other threads. But this cannot happen since *ptr is not a static data variable. Its a parameter variable and local and parameter variables being hold inside stack. Each thread has its own stack section and if *ptr has been changed by another thread, it should not effect the current thread's.
One reason why the result might not give the square can be an HW interrupt might happen before assigning b = *ptr; operation as indicated below:
int square(volatile int *ptr) {
int a,b;
a = *ptr; //assuming a is being kept inside CPU registers.
//an HW interrupt might occur here and change the value inside the register which keeps the value of integer "a"
b = *ptr;
return a * b;
}