Below is the a sample C Program which provides the output followed after the program
#include<stdio.h>
void newfunc(int n);
int main(void)
{
newfunc(2);
return 0;
}
void newfunc(int n)
{
printf("\n%d",n);
if(n<50)
{
newfunc(2*n);
printf("\n%d",n);
}
}
produces output
2
4
8
16
32
64
32
16
8
4
2
But according to the code, it seems that after the function call in line 13, the next printf is not called. And the output seems unnatural. I searched the internet and found something about stacks. Can someone elaborate why this happens?
This is a basic recursive call.
First, notice that for values of n less than 50 your function will print n twice, and for other values of n it will print only once. That agrees with your output,so the only thing to figure out here is the order...
Second notice that the output for n*2 should come between the first and second line of output from n (for n < 50), because you make the recursive call in between the two printfs. Well, that also agrees with your output.
This is as expected.
The part you found on the internet about stacks is referring to the call stack. In order to return from a function the program has to keep track of where it was when the function was called. This information is written to 'end' of a special part of memory called the "call stack" or "execution stack"; and it is taken off of the stack (meaning that the 'end' is moved when the function returns). Call parameters are also recorded on the stack.
This kind of stacking is essential to recursion.
So, when you call newfunc(2) the program records that it was on line 5, then jumps to the beginning of newfunc on line 8. The stack looks (notionally) like:
line 5, n=2
When it gets to line 13, it calls new function again, making the stack
line 5, n=2; line 13, n=4
This goes on several times until the stack looks like
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32; line 13, n=64
when the if fails and newfunc returns poping the stack and resuming execution after line 13 (because that is what we got off the stack) making the stack
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32
when we run printf and pop the stack as we return to line 13 (what we got when we popped, right>) so that the stack is
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16;
and so on while it unwinds the whole call stack.
A couple of final details: the stack notionally grows "up" so we often write it as
line 13, n=32
line 13, n=16
line 13, n=8
line 13, n=4
line 5, n=2
and the exact format of the stuff of the stack depends on the architecture of the chip and some decisions made by the OS programmers.
BTW--a c program doesn't typically use line numbers to denote "where" it was because lines are not good measures in c (I can write the whole program one one line if I'm silly enough), rather it uses the value of a register on the chip, but that doesn't really affect the explanation here.
What actually happens is, when you call the function in line 13 the code after the function cannot execute at that time, so they are stored in a special place in memory called stacks and they are filled up from bottom so newer codes fill in the top of the stacks. So at the first function call the printf("\n%d",2) is added to the stack at the bottom and printf("\n%d",4); i.e, 2 * n = 2 * 2 = 4 is added to top of the previous stack and when the recursive execution stops. the stack program from top is executed producing the above complex type of output not predictable to simple analysis.
Lets take it for small value say 10
1st call from main ////returned from newfunc(2)
newfunc(2)
//inside newfunc(2)
print 2
2<10 (correct)
newfunc(4) --> on stack print 2 //returned from newfunc(4)
-------------------------------
//inside newfunc(4)
print 4
4<10
newfunc(8) --> on stack print 4 //returned from newfunc(8)
---------------------------------
//inside newfunc(8)
print 8
8<10
newfunc(16) --> on stack print 8 //returned from newfunc(16)
---------------------------
//inside newfunc(16)
print 16
16<10 failed
so it will return to its previous function whichever has called it so it will go on --> symbol which is top of stack here for this example and print is used to show the result on screen
Function sequence is top to down ... I tried to show this in diagram. hope you get it.
here --> statement will be executed from bottom to top so the result will be
2
4
8
16
8
4
2
Related
(1)
Is there a way to count the number of steps it takes to execute a function or a thread with LLDB?
As an example,
#include<stdio.h>
int main()
{
printf("\n\n\t\tStudytonight - Best place to learn\n\n\n"); // step count: 1
int number;
int number2;
int number3;
number = 50; // step count: 2 (lldb skips declarations)
number = 60; // step count: 3
/*
Comment comment
*/
if(number < 100) // step count: 4 (lldb skips comments)
printf("Number is less than 100!\n"); // step count: 5
else if(number == 100)
printf("Number is 100!\n");
else
printf("Number is greater than 100!\n");
printf("\n\n\t\t\tCoding is Fun !\n\n\n"); // step count: 6 (the lines that are not executed bec of branching are not counted.)
return 0; // step count: 7
}
The step count is provided in the comments in the code above. And I only count step-overs.
The step count is unique to each execution of the code, and is expected to change if command line arguments and environment variables change and affect the control flow of the program.
If there are loops, each iteration will mean counting the lines in the loop again. So if there are 2 steps per iteration and there are 10 iterations, then there are 20 steps for that loop.
(2)
(Although I only count step-overs, I appreciate answers that also tell me how I can configure to include step-ins when I need them, or exclude them when I don't need them.)
(3)
In addition, is there a way to jump to a specific step in that step count? By this, I think of the jump command and How to skip a couple of lines code with lldb?.
However, what if the code has loops? Say:
for (i = 1; i < 11; ++i)
{
printf("%d ", i);
}
return 0;
}
There are 6 static lines of code (counting all those with only the curly brackets as well). However, the number of steps is probably 21. I wish I could jump to the 10th step, for example. Is it possible with lldb?
Another way to count steps is to write a scripted stepping plan that just keeps pushing new "step in" or "step over" plans till you reach whatever your terminating condition is, and updates some python variable each time an individual step is concluded. For more info on writing scripted thread plans, see:
https://lldb.llvm.org/use/python-reference.html#using-the-python-api-to-create-custom-stepping-logic
and there are several examples of scripted stepping plans here:
https://github.com/llvm/llvm-project/blob/master/lldb/examples/python/scripted_step.py
I'm not quite sure what you mean by "jumping to a specific step". If you mean you just what to stop at that point without having to manually intervene, it would be fairly straightforward to make a scripted stepping plan with whatever end conditions you want (the 10th time you hit line 20, or whatever).
But if you mean "get to that stage in the execution w/o going through the intervening code" that's not a trivial problem. How would lldb know what state was modified along the way to that point? For instance to get to a certain iteration of a loop, lldb would have to know to set the loop counter to whatever value it has at that point, which it has no way of knowing.
Instead of counting steps, and executing a counted number of steps, you can use breakpoints in most cases. For example, in the for loop example, a breakpoint can be configured to stop only under the right conditions.
For these examples, I'll assume the printf is on line 23 of file.c.
To stop part way through the loop, instead of executing a number of next commands, a breakpoint condition can be used to stop only when the loop index i is the desired number:
b file.c:23
breakpoint modify --condition 'i == 5'
The condition expression is a evaluated by lldb, so it can be more complex as needed.
In this case, since the condition is a count, another way of doing this is to set an ignore count on the breakpoint:
b file.c:23
breakpoint modify --ignore-count 5
Note: instead of --condition and --ignore-count, you can alternatively use -c and -i.
Im trying to implement custom threads in C by creating a simple context switch function plus a FCFS scheduler.
The first step that i want to perform is to copy the entire function stack frame to heap to a saved frame and replace it by the first in queue.
The problem i have is that after finishing task one the stack of the second gets corrupted. I dont have any idea about why.
The code i have is the following:
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define ITERATIONS 10
#define SSIZE 15
int * last;
void kwrite(const char*);
void kyield(int *);
void f1() {
int i = ITERATIONS;
while (i--) kwrite("A\n");
}
void f2() {
int i = ITERATIONS*2;
while (i--) {
printf("[%d]", i);
kwrite("B\n");
getchar();
}
}
void kwrite(const char* str) {
int a[10] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
write(1, str, strlen(str));
int *frame = malloc(sizeof(int)*SSIZE);
memcpy(frame, a, SSIZE*sizeof(int));
kyield(frame);
printf("ERROR\n");
}
void kyield(int * from) {
if (from == NULL) {
f1();
from = malloc(sizeof(int)*SSIZE);
memcpy(from, last, SSIZE*sizeof(int));
}
if (last == NULL) {
last = malloc(sizeof(int)*SSIZE);
memcpy(last, from, SSIZE*sizeof(int));
free(from);
f2();
exit(0);
}
int a[10] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
memcpy(a, last, SSIZE*sizeof(int));
memcpy(last, from, SSIZE*sizeof(int));
free(from);
}
int main(int argc, char** argv) {
kyield(NULL);
free(last);
}
It should call 10 times f1 and 20 f2 then exit. But when the var i of f2 is 8 it gets corrupted on the next iteration. Therefore entering an infinite loop.
Any help or suggestions would be appreciated! Have a nice day.
[edit]
I suppose the code can be a bit tricky to understand so here it is a little clarification:
main calls kyield with null parameters.
kyield detects it and calls f1
f1 executes until kwrite is called
kwrite calls kyield passing its current stack frame
kyield detects the last stack frame is null so it copies the stack frame (sf from now on) given by kwrite, then calls f2
f2 does the same as f1
when kyield is executed next, both from and last wont be NULL so it will overwrite its current s f with the one in last, swap it with the one in from and lastly it will return, as the stack has been altered it will jump to the return address of the last kwrite, not the actual one, thus. Jumping from the f1 thread to f2.
Your memcpy(frame, a, SSIZE*sizeof(int)) looks wrong. Your SSIZE is defined to 15, but a has only a size of 10.
this is deliberate, as by copying 15 elements of 4 bytes we are copying the rax last value, the last ebp and the return address of the function.
https://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64/
I can see a couple of issues with the design. The normal way of scheduling different threads is for them to get complete stacks, not to share the same stack.
What that means in this case, is that the stack depends on the addresses being used.
+---------+--------+---------+--------+---------+
| main | kyield | f1 | kwrite | kyield |
| | | |a[10] | |
+---------+--------+---------+--------+---------+
|-------------| << copied by the slice of the stack.
The slice of the stack you are taking, is independent of the amount used in the function preceding it, so would be broken if the functions calling kwrite have different stack requirements (different amounts of state would be required).
It is also broken because the amount of information which is captured on the stack is not complete. The state of execution is based on the stack and the current values in non-volatile registers. These values can pollute the alternate threads.
Finally the stack also contains addresses. This scheme could only work, if all the threads executed had identical stack requirements, as if the yield function pastes a value back in which requires addresses, then they always have to align.
Your memcpy(frame, a, SSIZE*sizeof(int)) looks wrong. Your SSIZE is defined to 15, but a has only a size of 10.
so , I will to Understand debugging , i am very new and I am not a IT student.. .I am since Three Days this exercise to Understand , but without sucess...
I working with Linux and the Program GDB:
1 #include <string.h>
2 #include <stdio.h>
3
4 void overflowed() {
5 printf("%s\n", "Execution Hijacked");
6 }
7
8 void function1(char *str){
9 char buffer[5];
10 strcpy(buffer, str); (**3**)
11 } (**2**)
12 void main(int argc, char *argv[])
13 {
14 function1(argv[1]); (**1**)
15 printf("%s\n", "Executed normally");
16 }
The Number 1 , 2 , 3 are the Program Break Punkt .
(gdb) break 14
Breakpoint 1 at 0x8048433: file overflowtest.c, line 14.
(gdb) break 10
Breakpoint 2 at 0x804840e: file overflowtest.c, line 10.
(gdb) break 11
Breakpoint 3 at 0x8048420: file overflowtest.c, line 11.
Break the line 14,10 and 11 .
than with run to given Four A
(gdb) run AAAA
Starting program: /home/georgia/overflowtest AAAA
Breakpoint 1, main (argc=2, argv=0xbfb73004) at overflowtest.c:14
14 function(argv[1]);
than with x/16xw $esp to my First Break ,line 14 , i come
(gdb) x/16xw $esp
0xbfb72f50: 0xb77e6ff4 0x08049ff4 0xbfb72f78 0x08048489
0xbfb72f60: 0xb780a7b0 0xbfb72f80 0xbfb72fd8 0xb769e775
0xbfb72f70: 0x08048470 0x08048340 0xbfb72fd8 0xb769e775
0xbfb72f80: 0x00000002 0xbfb73004 0xbfb73010 0xb77fab40
so, i to search to Understand , what on the far left is 0xbfb72f50: and all Hex back from it come, his meaning.... . Can Please anybody help me with easy Words explain , to describe it ? , Very Thanks!
The first column is the address, that is, on the first line, the value of the %esp register.
For an explanation of the stack pointer (%esp) and stack frame (%ebp) registers, consult a text on compiler construction, such as chapter 6, Activation Records, in Appel's Modern compiler implementation in ML. Relevant keywords are activation records and stack frames. Wikipedia has some basic information, too.
So , How i Understande the Memory Adress on the far left :
0xbfb72f50:
0xbfb72f60:
0xbfb72f70:
0xbfb72f80:
are the stack framen where start my Three breakpoints ,but i don't know what the Fisrt Adress to do.... , sorry about this questions , but i am not a Student from IT ....i learn self to Home....
So , answer me self:
Far left are the Memory Adress and what First back to come are the Content-addressable memory , 0xb77e6ff4 is the ESP of the main ’s stack frame . ESP marks the lowest memory address of a Stack , EBP is the highest address , Here 0xbfb72f78 .
I'm a beginner at C programming and I would appreciate some help in order to understand the problem.
Alright so, I have a data file (input.dat) with data like this: (first line) 0 2 3 4 5; (second line) 1 2 3 5 4, (third line and so on...). I'm required to read the data one line at a time until the end of file and print it. This is what I have done so far:
int main(void)
{
float coeffs[5];
FILE *input; /* File pointer to the input file */
fopen_s(&input, "input.dat", "r"); /* Location of the input file */
int count = 0;
/* Loops to read data set*/
while (fscanf_s(input, "%f %f %f %f %f ", &coeffs[0], &coeffs[1], &coeffs[2], &coeffs[3], &coeffs[4]) != EOF)
{
printf("a=%.4f; b=%.4f; c=%.4f; d=%.4f; e=%.4f\n", coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4]);
count++;
}
return 0;
}
This is showing all of the lines in the data file at once. But this is not what I want. I need to read one line at a time and perform some calculations and conditions for that one line first before I move to the next line. So how can I do that?
Next problem is, for the first line, I need to implement a loop from -10 to +10 with increment of 2 (to get 11 results in total). For example the program will read the first line, display it on the screen, then for the first value -10, the program will calculate and again display something . Then it will do the same for -8, then for -6 and so on until +10. After the 11 results are displayed, the program will then and ONLY then, move to the second line and so on. Hence for each line in the data file, the program will have 11 results. How can I use the loop function with increment of 2 to achieve these 11 results?
I would appreciate if anyone can provide me a simple layout of the structure of the codes which I've to write. NOTE: The formats are a bit different than other compilers as I must use Microsoft Visual Studio to do it.
Add your calculations to your while loop. You are reading one line at a time anyway.
If you want to loop from -10 to 10 with increments of 2, use a for loop.
for(count = -10; count <= 10; count = count + 2)
{
// Calculations
}
Is it possible to dump the entire program steps to a file? I don't mean the value of the variables, I mean the jumping from on instruction to another, and if it's possible to use both, steps and the var values
I've used both gdb and GUI(ddd), and I use the regular step all the time but sometimes I have a loop and network application so I don't want to affect the flaw of the program, I just want to see what happened exactly after everything is done.
For instance,
1 #include<stdio.h>
2
3 int main()
4 {
5
6 int i = 0, y = 0;
7
8 for (y; y< 10; y++) {
9 i++;
10 printf("%d\n", i)
11 }
12 return 0;
13
14 }
So the dump file will contain all the steps from int main() to return 0, like below for example
1. on 1
2. on 2
...
...
8. on 8
9. on 9
10. on 10
11. on 8
12. on 9
... and so on until the loop finishes and then hit return and exit.
Using GDB you could use process record and replay. Another option is Jockey which functions as a record/replay preload library.