I am writing the following code that will be able to change the stack of function call. but it always runs into segfault on printf. I debugged the code with assembly, the stack was successfully switched. it is the printf statement that created the segfault and not sure the reason. anybody has any clue what direction i should look into more?
Thanks.
char stack[4000000*4];
void foo(int ad) {
int i = 100;
int sum = i*i + ad;
printf("stack changed to %X\n", stack);
}
/* in this example, foo (and its decendents) live on a new stack */
void change_stack(void *newstack) {
void *ctx[5]; // Jump buffer for setjmp/longjmp.
if (0 == __builtin_longjmp(ctx)) {
ctx[2] = newstack; // switch stack
__builtin_longjmp(ctx, 1);/* here stack is switched */
} else {
/* now live on new stack, can we pass parameters now ? */
int ad = 20;
foo(ad);
}
}
int main (int argc, char** argv)
{
int i = 10;
change_stack(stack);
printf("return, %d\n", i);
return 0;
}
You switch stacks without copying the contents of the old one. When change_stack returns, the results are undefined (it may, for example, jump to address NULL, causing a segfault). Also, things like local variables will also be undefined.
Also, (assuming we're talking x86 here), the stack pointer is decremented on pushes. Since the new stack pointer you assigned is the base (i.e. lowest) address of your stack array, any push will decrease the pointer outside of this array, also possibly resulting in a segfault.
To anyone who still wants to play with the stack and also encountered SIGSEGV in printf, here is an important point:
You can find one of the subroutines of printf, __GI___tcgetattr under /path-to-glibc/sysdeps/unix/sysv/linux/tcgetattr.c. There is one instrution in it:
movdqa (%rsp),%xmm0
And according to this answer, it reads 16-byte align memory from source address. So you should keep the address of %rsp at least 16-byte address align when you switch the stack, otherwise you will get a SIGSEGV.
Related
I was wondering if there is a function in C (let's dub it int get_stack_depth()), which returns the amount of functions currently being executed on the stack. For example:
int foo(){
return get_stack_depth();
}
int bar2(){
return get_stack_depth();
}
int bar1(){
return bar2();
}
int bar(){
return bar1();
}
int main(){
get_stack_depth(); // = 0
foo(); // = 1
bar(); // = 3
return 0;
}
I would like to use it for debugging info, where each printf would contain get_stack_depth() indents to increase readability. If this is compiler dependent, or anything-else dependent, I take all the constraints; right now I wonder whether this is supported at least somewhere.
EDIT: The answer at the suggested duplicate didn't help me at all, as the accepted answer here suggests, you cannot determine how many functions are on the stack based purely upon the size of the stack; the information is simply not there.
The exact mechanics of the stack in C are implementation-specific, so there is no single, correct, standard way to find the depth of the stack. There are some methods to simulate this behavior, though.
Use a counter. Define a global unsigned depth, and in each function in which you care about the depth of the stack, inject depth++ at the beginning and depth-- at the end. This is obviously the more tedious method, and it's prone to a lot of frustrating issues if an increment or decrement is left off.
Check the stack pointer. On x86 systems (virtually every desktop & laptop device), the stack grows downward, meaning that entering a function call will decrease the value of the stack pointer. In many cases (but not all, e.g. when optimization is enabled) the stack pointer register, %rsp, points to the "top" of the current function's stack frame. A rather hacky way to fetch this value is to assign it to a variable: register uint64_t rsp asm ("rsp");. The lower the value, the greater the depth on the stack.
Unfortunately, the size of the decrement between function calls depends on how large the stack frame for that function is—if one function declares a large array as a local variable, then the stack pointer will be much lower for functions it calls, since more space is consumed by the array.
Ultimately the only reliable way I know of to find an accurate backtrace of function calls is to run the program in a debugger such as gdb and issue the backtrace command, which will print the current call stack. This kind of support just doesn't seem to be available to the program when it is run independent of any debugger.
Have you tried using backtrace()?
for example:
#include <execinfo.h>
unsighed int getDepth(){
const unsigned int max_depth = 200;
void* buffer[max_depth];
return backtrace(buffer, max_depth)-5;
}
The -5 is there because there are some functions above main (added by the libc) that I want to ignore. However, if you want to calculate that automatically, change my function to
int get_stack_depth(int set_caller_as_root){
static int root_depth = 0;
if (set_caller_as_root){
root_depth = get_stack_depth(0) - 1;
}
const int max_depth = 200;
void* buffer[max_depth];
return backtrace(buffer, max_depth) - root_depth;
}
and update your code to
int foo(){
return get_stack_depth(0);
}
int bar2(){
return get_stack_depth(0);
}
int bar1(){
return bar2();
}
int bar(){
return bar1();
}
int main(){
printf("%d\n", get_stack_depth(1)); // = 0
printf("%d\n", foo()); // = 1
printf("%d\n", bar()); // = 3
return 0;
}
which yields the correct, expected results.
Note that execinfo.h is not installed on windows 10 by default (it is on linux).
Thinking about returning dynamic or automatic arrays. Not really C-related.
The usual technique to return an array is: A) callee allocates on heap and returns, B) caller allocates on stack and passes to callee.
// A
void caller(void) {
int *a = callee();
free(a);
}
int *callee(void) {
int *a = malloc(10 * sizeof(*a));
return a;
}
// B
void caller(void) {
int a[10]; callee(a, sizeof(a) / sizeof(a[0]));
}
void callee(int *a, size_t n) {
//
}
Case A may lead to unnecessary allocate-free cycle, while case B requires syntactic garbage in caller. In B we also can't compute n in callee, because it comes predefined. We also can't return automatic storage because it will be destroyed on return (accessing it is UB in general).
But what if we introduce new return_auto operator that will return from callee, but leave it's stack frame intact, as if caller did all the job on it's own stack?
// C
void caller(void) {
int *a = callee();
}
int *callee() {
int a[compute_n()];
return_auto a;
}
I mean, caller could inherit callee's stack frame and all issues disappear. It's stack frame would look like this after return_auto:
[caller frame]
arguments
ret-pointer
locals
int *a = callee.a
[callee frame] (defunct)
arguments
ret-pointer
locals
int a[n] (still alive)
[end-of-callee-frame]
[end-of-caller-frame]
In machine code (x86 at least) this may be implemented by jumping to ret-pointer at ss:ebp instead of mov esp, ebp / ret n. We already have VLAs in modern C, and this looks very similar but slightly complex.
Of course that should be used with care, because series of return_auto's would leave pretty huge dump on stack, that will be "collected" only when outermost caller returns (normally). But stack allocations are insanely cheap, and in theory some algorithms could benefit from not calling malloc/free at all. This is also interesting in code structuring perspective, not just performance.
Does anyone know where this technique is implemented / stack frames joined?
(C is just an example here)
Okay, it needs a simple example.
void caller(Context *ct) {
char *s = make_s(ct);
printf("%s\n", s);
}
void make_s(Context *ct) {
const char *tag = "?", *name = "*";
if (ct->use_tag) tag = ct->tag;
else if (ct->app) tag = ct->app->tag;
if (ct->app) name = ct->app->name;
char s[strlen(tag)+strlen(name)+10];
snprintf(s, len, "%s.object(%s)", name, tag);
return_auto s;
}
Obviously, for now we need to explode that in caller's body (probably via macro to feel all caveats) or do asprintf/malloc in callee and free in caller.
This seems a very bad idea for any non-trivial scenario. Just remember a stack frame contains all the local variables along with return address, saved base pointer, and so on. In your model, a caller would need to "inherit" the whole frame as part of its own frame. Then think about you might pass this returned value to some OTHER function. So what if this function wants to return more than just an integral value? You would easily end up with a huge stack frame for main(). Any heap implementation is probably more space efficient.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 years ago.
This is a question from a C language course. Someone wants to return a value from a function with a pointer. He assigns the pointer address to result_ptr and prints this pointer's value.
When there is no Line A, printf() works fine: printf() prints 3.
However, when another addition() function is called in front of the printf(), something wrong happens: the printf() prints 5.
If Line A is commented out and Line B, another printf() function, is uncommented: the printf() prints 0.
What exactly is going on?
int *addition(int a, int b) {
int d = a + b;
int *c = &d;
return c;
}
int main(int argc, const char * argv[])
{
int *result_ptr = addition(1, 2);
addition(2, 3); // Line A
// printf("Another line\n"); // Line B
printf("result = %d \n", *result_ptr);
return 0;
}
When a function is called, the arguments (in reversed order), the return address and the Caller's EBP (which stores where the function returns to after execution) are pushed onto the stack. The callee setups a stack frame that stores its local variables and saves contents of 3 registers, EBX, ESI and EDI if they are modified. When the function finishes execution, the frame is popped and the stack's top returns to the height where it had been before the callee was called.
In this example, int *c declares a local pointer variable that is stored on the stack within the callee's frame. Returning that pointer is returning an address on the stack frame. As consecutive addition() calls cause identical stack space allocations, content of the same address will be written twice. This is why the second function call will write 5, overwriting 3 from the first function call: they are modifying the value at the same memory location. When printf() is called, however, the stack space is used for a totally different stack frame. Then the same location stores an undefined value.
To avoid this, it would be better to return a pointer to a location on the heap instead of on the stack. Mind to free the pointer after memory allocation to avoid leakage.
int *addition(int a, int b) {
int *c = (int *) malloc(sizeof(int));
*c = a + b;
return c;
}
// in main
int *result_ptr=addition(1,2);
printf("value = %d \n",result_ptr);
free(result_ptr);
result_ptr=0;
Reference: http://www.csee.umbc.edu/~chang/cs313.s02/stack.shtml
I will be glad to see clearer or different explanations for this question.
While learning pointers I tried pointer declarations/dereferenciations.
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int *call() {
int a = 3;
return &a;
}
int main() {
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
Sleep(2000);
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
Sleep(2000);
printf("call* is: %d\n", *call());
printf("call is: %p\n", call());
return 0;
}
So "obviously" the "a" is a local variable.
But my problem is,
when I'm reading out the address of "a", it's always the same address.
Why is that like this?
PS: I'm running a prime-number-calculator in the background to fill up as much memory as possible and I put in the "Sleep" to make the program wait, but still the address of "a" is always the same.
a is located on the stack of the current thread : every time the function call() is run, it "allocates" 4 bytes on the stack to stock a, return the address and then "frees" the space it uses on stack (it is not actually allocating/freeing anything, just offsetting the stack pointer).
So if you call it several times in a row, the state of the stack on input of the function will be exactly the same, so the actual address of a on the stack the same every time (please note that this address is invalid as soon as you exit the function).
You should do something like
int * call2(){
int a = 0;
int *b = call();
printf("%d",a);
return b;
}
and then
int *a = call();
int *b = call2();
You will see a and b will be different (the printf is there to make sure the compiler does not optimise anything away)
Since the stack is local to the current thread (not influenced by other processes/threads), your prime number calculator and Sleep are to no use at all.
"call" is to return a pointer to a variable? The problem here is that "a" is not statically allocated, but is on the stack. You can return its address at the moment (which may or may not be the same address, depending on whether "call" is invoked at the same depth each time), but there's no guarantee of what that address is pointing to once you return from "call". You put a 3 in it during the call, and that may be overwritten by something else by the time you get around to looking at the contents of that address.
Update : Sorry, just a big mistake. It is meaningless to write int *a = 3; But please just think the analogy to the case like TCHAR *a = TEXT("text"); (I edited my question, so some answers and comments are strange, since they are for my original question which is not suitable)
In main function, suppose I have a pointer TCHAR *a = TEXT("text"); Then it excutes the following code:
int i;
for (i = 0; i < 1000; i++) {
a = test(i);
}
with the function TCHAR* test(int par) defined by:
TCHAR* test(int par)
{
TCHAR *b = TEXT("aaa");
return b;
}
My question is, after executing the above code, but before the program ends, in the memory:
1. the pointer `a` remains?
2. The 1000 pointers `b` are deleted each time the function test(...) exits ?
3. But there are still 1000 memory blocks there?
In fact, my question is motivated from the following code, which shows a tooltip when mouse is over a tab item in a tab control with the style TCS_TOOLTIPS:
case WM_NOTIFY
if (lpnmhdr->code == TTN_GETDISPINFO) {
LPNMTTDISPINFO lpnmtdi;
lpnmtdi = (LPNMTTDISPINFO)lParam;
int tabIndex = (int) wParam; // wParam is the index of the tab item.
lpnmtdi->lpszText = SetTabToolTipText(panel->gWin.At(tabIndex));
break;
}
I am thinking if the memory usage increases each time it calls
SetTabToolTipText(panel->gWin.At(tabIndex)), which manipulates with TCHAR and TCHAR* and return a value of type LPTSTR.
Yes, the pointer a remains till we return from the main function
The variable b (a 4-byte pointer) is automatic. It is created each time we call test function. Once we return from it, the variable disappears (the pointer). Please note, the value to which b points isn't affected.
No. In most of the cases, I think, there will be only one block allocated during compilation time (most likely in the read-only memory) and the function will be returning the same pointer on every invocation.
If SetTabToolTipText allocates a string inside using some memory management facilities new/malloc or some os-specific, you should do an additional cleanup. Otherwise there'll be a memory leak.
If nothing like this happens inside (it's not mentioned in the documentation or comments etc), it's most likely returning the pointer to some internal buffer which you typically use as readonly. In this case, there should be no concerns about a memory consumption increase.
You dont allocate any memory so you don't have to worry about memory being freed. When your vaiables go out of scope they will be freed automatically. In this function
int test(int par)
{
int *b = par;
}
you don't have a return value even though the function says that is will return an int, so you should probably do so as in this line
for (i = 0; i < 1000; i++) {
a = test(i);
}
you assign to a the value that is returned by test(). Also
int* a = 3;
int* b = par;
are asking for trouble. You are assigning integer values to a pointer variable. You should probably rethink your above code.
Pointer should contain adress... so int* a = 3 is something meaningless... And in function you don't allocate memory for int (only for par variable, which then destroy when the function ends), you allocate memory for storing adress in int* b, this memory also free when the funciton ends.