How two independent jmp_bufs work? - c

Hi I want to ask about setjmp/longjmp. I tried to search, but I was unsucessuful...
#include <stdio.h>
#include <setjmp.h>
jmp_buf a, b;
void jump() {
int aa = setjmp(a);
if (aa)
{
printf("Jump!\n");
}
else
{
longjmp(b, 1);
printf("Should not happened...\n");
}
printf("End of function!\n");
}
int main(int argc, char** argv) {
int bb = setjmp(b);
if (bb)
{
longjmp(a, 1);
printf("Should not happened...\n");
}
else
{
jump();
printf("What here?\n");
}
printf("Exit\n");
return 0;
}
The question is, what will happen after last printf in jump()... I tried this code and it turned into infinite loop. Why? I though that setjmp will store environment data, so the jump function shall return after it's original call... I'm quiet confused. Thanks for reply :)

The whole program has undefined behavior.
setjmp(b); stores the stack state.
jump() is called.
`setjmp(a);' stores the stack state again.
longjmp(b, 1); restores the stack to the point before jump() was ever called. So the state stored in a is now invalid.
Execution continues at the if in main().
longjmp(a, 1); is called. Ouch. This causes undefined behavior due to 4 above.
Your confusion probably results from the slightly imprecise use of the world "return" in the Linux docs for setjmp().
The stack context will be invalidated if the function which called setjmp() returns.
In your example, the function jump() didn't return in the normal way, but the effect was the same: the stack was "chopped" by the first longjmp() to the state before jump(), which is what a return does, too.

Related

Does it matter where in my program I call atexit()?

Basically, I am writing a program in SDL.
This is part of the code:
// create game window
game.window = SDL_CreateWindow(
"Game",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
160,
144,
0
);
if (game.window == NULL)
{
fprintf(stderr, "Window error: %s\n", SDL_GetError());
return 1;
}
atexit(SDL_DestroyWindow());
atexit(SDL_Quit());
return 0;
}
My question is the following. Considering the procedural nature of C, what happens if (game.window == NULL) is the case and return 1 executes. Does the program terminate with return 1 without calling the atexit() functions that come after this if-statement?
Does the program still call SDL_DestroyWindow() and SDL_Quit(), which are both in atexit() functions despite the atexit() functions coming after the return 1 in the if (game.window == NULL)-statement?
As far as I understand, C executes code from top to bottom, so how would it know to call the functions in atexit() at the end if return 1 happens before?
You're right, it wont call those functions registered with atexit().
To show this behaviour I wrote a small code snippet.
#include <stdlib.h>
#include <stdio.h>
void bye()
{
printf("Bye!\n");
}
int main(int argc, char *argv[])
{
int i = 1;
if (i) {
printf("Ending\n");
return 0;
}
atexit(bye);
return 0;
}
And this won't print the "Bye!", as the atexit() is registered after the check for i.
First of all, you cannot destroy the window before you know for true you have it created So the call to atexit(3) to register the function to destroy the window must be done after you know the window exists. (this is after the } closing bracket of the if)
The call to atexit(SDL_Quit); might be done once you have the SDL environment intialized (this is after it has been correctly inited, so it will be called only for a truly intialized environment) but it must be called before the call to register the destroy of the SDL window, as atexit(3) makes the functions you register, to be called in reverse order so it must first desroy the window and then close the SDL environment (and there will be no sense to call a function that destroys a window when the SDL has already been closed).
By the way, atexit() requires the function pointers, not the result of the function call. Better to write
atexit(SDL_Quit);
atexit(SDL_DestroyWindow);
Than what you have written.
NOTE
If the functions need parameters, better to write function wrappers to call them with the appropiate parameters.

Accessing the variable inside another code

Is there a way to access a variable initialized in one code from another code. For eg. my code1.c is as follows,
# include <stdio.h>
int main()
{
int a=4;
sleep(99);
printf("%d\n", a);
return 0;
}
Now, is there any way that I can access the value of a from inside another C code (code2.c)? I am assuming, I have all the knowledge of the variable which I want to access, but I don't have any information about its address in the RAM. So, is there any way?
I know about the extern, what I am asking for here is a sort of backdoor. Like, kind of searching for the variable in the RAM based on some properties.
Your example has one caveat, set aside possible optimizations that would make the variable to dissapear: variable a only exists while the function is being executed and has not yet finished.
Well, given that the function is main() it shouldn't be a problem, at least, for standard C programs, so if you have a program like this:
# include <stdio.h>
int main()
{
int a=4;
printf("%d\n", a);
return 0;
}
Chances are that this code will call some functions. If one of them needs to access a to read and write to it, just pass a pointer to a as an argument to the function.
# include <stdio.h>
int main()
{
int a=4;
somefunction(&a);
printf("%d\n", a);
return 0;
}
void somefunction (int *n)
{
/* Whatever you do with *n you are actually
doing it with a */
*n++; /* actually increments a */
}
But if the function that needs to access a is deep in the function call stack, all the parent functions need to pass the pointer to a even if they don't use it, adding clutter and lowering the readability of code.
The usual solution is to declare a as global, making it accessible to every function in your code. If that scenario is to be avoided, you can make a visible only for the functions that need to access it. To do that, you need to have a single source code file with all the functions that need to use a. Then, declare a as static global variable. So, only the functions that are written in the same source file will know about a, and no pointer will be needed. It doesn't matter if the functions are very nested in the function call stack. Intermediate functions won't need to pass any additional information to make a nested function to know about a
So, you would have code1.c with main() and all the functions that need to access a
/* code1.c */
# include <stdio.h>
static int a;
void somefunction (void);
int main()
{
a=4;
somefunction();
printf("%d\n", a);
return 0;
}
void somefunction (void)
{
a++;
}
/* end of code1.c */
About trying to figure out where in RAM is a specific variable stored:
Kind of. You can travel across function stack frames from yours to the main() stack frame, and inside those stack frames lie the local variables of each function, but there is no sumplementary information in RAM about what variable is located at what position, and the compiler may choose to put it wherever it likes within the stack frame (or even in a register, so there would be no trace of it in RAM, except for push and pops from/to general registers, which would be even harder to follow).
So unless that variable has a non trivial value, it's the only local variable in its stack frame, compiler optimizations have been disabled, your code is aware of the architecture and calling conventions being used, and the variable is declared as volatile to stop being stored in a CPU register, I think there is no safe and/or portable way to find it out.
OTOH, if your program has been compiled with -g flag, you might be able to read debugging information from within your program and find out where in the stack frame the variable is, and crawl through it to find it.
code1.c:
#include <stdio.h>
void doSomething(); // so that we can use the function from code2.c
int a = 4; // global variable accessible in all functions defined after this point
int main()
{
printf("main says %d\n", a);
doSomething();
printf("main says %d\n", a);
return 0;
}
code2.c
#include <stdio.h>
extern int a; // gain access to variable from code1.c
void doSomething()
{
a = 3;
printf("doSomething says %d\n", a);
}
output:
main says 4
doSomething says 3
main says 3
You can use extern int a; in every file in which you must use a (code2.c in this case), except for the file in which it is declared without extern (code1.c in this case). For this approach to work you must declare your a variable globally (not inside a function).
One approach is to have the separate executable have the same stack layout as the program in question (since the variable is placed on the stack, and we need the relative address of the variable), therefore compile it with the same or similar compiler version and options, as much as possible.
On Linux, we can read the running code's data with ptrace(PTRACE_PEEKDATA, pid, …). Since on current Linux systems the start address of the stack varies, we have to account for that; fortunately, this address can be obtained from the 28th field of /proc/…/stat.
The following program (compiled with cc Debian 4.4.5-8 and no code generator option on Linux 2.6.32) works; the pid of the running program has to be specified as the program argument.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
void *startstack(char *pid)
{ // The address of the start (i. e. bottom) of the stack.
char str[FILENAME_MAX];
FILE *fp = fopen(strcat(strcat(strcpy(str, "/proc/"), pid), "/stat"), "r");
if (!fp) perror(str), exit(1);
if (!fgets(str, sizeof str, fp)) exit(1);
fclose(fp);
unsigned long address;
int i = 28; char *s = str; while (--i) s += strcspn(s, " ") + 1;
sscanf(s, "%lu", &address);
return (void *)address;
}
static int access(void *a, char *pidstr)
{
if (!pidstr) return 1;
int pid = atoi(pidstr);
if (ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) return perror("PTRACE_ATTACH"), 1;
int status;
// wait for program being signaled as stopped
if (wait(&status) < 0) return perror("wait"), 1;
// relocate variable address to stack of program in question
a = a-startstack("self")+startstack(pidstr);
int val;
if (errno = 0, val = ptrace(PTRACE_PEEKDATA, pid, a, 0), errno)
return perror("PTRACE_PEEKDATA"), 1;
printf("%d\n", val);
return 0;
}
int main(int argc, char *argv[])
{
int a;
return access(&a, argv[1]);
}
Another, more demanding approach would be as mcleod_ideafix indicated at the end of his answer to implement the bulk of a debugger and use the debug information (provided its presence) to locate the variable.

Function Pointers - Why does this code crash?

#include <stdio.h>
int main(void)
{
int (*fp)(void);
printf("Loopy.\n");
fp = &main; //point to main function
fp(); //call 'main'
return 0;
}
Instead of infinitely executing the loop, the "loop" executes for around 10-20 seconds on my machine then gets the standard Windows app crash report. Why is this?
Compiler: GCC
IDE: Code::Blocks
OS: Win7 64bit
10..20 seconds is about as long as it takes your computer to overflow the stack.
A new stack frame is created every time that your function calls itself recursively through a function pointer. Since the call is done indirectly, the compiler does not get a chance to optimize the tail call into a loop, so your program eventually crashes with stack overflow.
If you fix your program to stop looping after a set number of times, say, by setting up a counter, your program would run correctly to completion (demo).
#include <stdio.h>
int counter = 200;
int main(void)
{
int (*fp)(void);
printf("Loopy %d\n", counter);
fp = &main; //point to main function
if (counter--) {
fp(); //call 'main'
}
return 0;
}
The behavior is compiler dependent it may crash after stack overflow or just hang there without no response, but the only reason can be pushing too many stack frames in the memory stack

Any benefit of using assert instead of using a simple "if" ?

Given this code :
#include <stdio.h>
#include <assert.h>
void print_number(int* somePtr) {
assert (somePtr!=NULL);
printf ("%d\n",*somePtr);
}
int main ()
{
int a=1234;
int * b = NULL;
int * c = NULL;
b=&a;
print_number (c);
print_number (b);
return 0;
}
I can do this instead :
#include <stdio.h>
#include <assert.h>
void print_number(int* somePtr) {
if (somePtr != NULL)
printf ("%d\n",*somePtr);
// else do something
}
int main ()
{
int a=1234;
int * b = NULL;
int * c = NULL;
b=&a;
print_number (c);
print_number (b);
return 0;
}
So , what am I gaining by using assert ?
Regards
assert is to document your assumptions in the code. if statement is to handle different logical scenarios.
Now in your specific case, think from the point of view of the developer of the print_number() function.
For example when you write
void print_number(int* somePtr) {
assert (somePtr!=NULL);
printf ("%d\n",*somePtr);
}
you mean to say that,
In my print_number function I assume that always the pointer coming is not null. I would be very very surprised if this is null. I don't care to handle this scenario at all in my code.
But, if you write
void print_number(int* somePtr) {
if (somePtr != NULL)
printf ("%d\n",*somePtr);
// else do something
}
You seem to say that, in my print_number function, I expect people to pass a null pointer. And I know how to handle this situation and I do handle this with an else condition.
So, sometimes you will know how to handle certain situations and you want to do that. Then, use if.
Sometimes, you assume that something will not happen and you don't care to handle it. You just express your surprise and stop your program execution there with assert.
The difference is that assert is enabled only for debug build; it is not enabled for release build (i.e when NDEBUG is defined), which means in the release build there will be no check; as a result, your code will be little bit faster, compared to the one in which you use if condition which remains in the release build as well.
That means, assert is used to check common errors when you write the code, and catch them as soon as possible, in the development phase itself.
Lots of reasons:
Asserts are usually removed for release builds.
Asserts will report failure information to the client. if() does nothing by itself.
Because asserts are usually macros, you can also get code information about the failing assertion.
Assert is more semantically clear than if().
If assertion fails, you will see the output containing the failed assertion itself, plus the function and the line of the failed assert, something like:
test: main.cpp:9: int main(): Assertion `0==1' failed.
So, if your program crashes in runtime, you will see the exact reason and location of the crash.
There's a big article about assertions in wiki.
Assert will inform you that something wrong happend, possibly error to be fixed. In debug mode it will break and show callstack that will help you with fixing bug. So its a good practice to use. I would actually use if() and assert, because in Release your asserts should be turned off:
void print_number(int* somePtr) {
assert(somePtr != NULL);
if (somePtr != NULL)
printf ("%d\n",*somePtr);
// else do something
}
in " // else do something " you might think of throwing exception or returning error code.
Listen If Your (if) statement becomes True or False so compiler go for the next instructions.
But in assert.h when your statement becomes false "Program Terminates immediately" with assertion message.
EXAMPLE :*
#include <assert.h> #include <stdio.h>
int main () {
int a;
printf("Enter an integer value: "); scanf("%d", &a); assert(a >= 10);
printf("Integer entered is %d\n", a);
return(0); }

What is weird about wrapping setjmp and longjmp?

I am using setjmp and longjmp for the first time, and I ran across an issue that comes about when I wrap setjmp and longjmp. I boiled the code down to the following example:
#include <stdio.h>
#include <setjmp.h>
jmp_buf jb;
int mywrap_save()
{
int i = setjmp(jb);
return i;
}
int mywrap_call()
{
longjmp(jb, 1);
printf("this shouldn't appear\n");
}
void example_wrap()
{
if (mywrap_save() == 0){
printf("wrap: try block\n");
mywrap_call();
} else {
printf("wrap: catch block\n");
}
}
void example_non_wrap()
{
if (setjmp(jb) == 0){
printf("non_wrap: try block\n");
longjmp(jb, 1);
} else {
printf("non_wrap: catch block\n");
}
}
int main()
{
example_wrap();
example_non_wrap();
}
Initially I thought example_wrap() and example_non_wrap() would behave the same. However, the result of running the program (GCC 4.4, Linux):
wrap: try block
non_wrap: try block
non_wrap: catch block
If I trace the program in gdb, I see that even though mywrap_save() returns 1, the else branch after returning is oddly ignored. Can anyone explain what is going on?
The longjmp() routines may not be called after the routine which called
the setjmp() routines returns.
In other words, you are screwing up your stack.
You might take a look at the assembly to see if you can piece together what's really happening.
setjmp() will save the current call stack and mark a point. When the call stack grows, no matter how far from the marked point, you can use longjmp() to go to the marked point, like you never left the point.
In your code, when returning from mywrap_save(), the marked point was no longer valid, the stack space around the point was dirty, hence you cannot go back to a dirty point.

Resources