How to track a flow of a c program? - c

I'ts more of a general question: how to handle the execution path of a c program, which consist of multiple functions?
For example, i have a following c program:
void test_if_statement(int num)
{
if (num > 0)
//do smth
;
else
//do smth else
;
}
int main(void)
{
int num;
printf("enter an int value:");
scanf("%d", &num);
test_if_statement(num);
return 0;
}
Currently i'm using something like this to see where did my function go in if statements:
void test_if_statement(int num)
{
if (num > 0)
printf("i'm here\n");
//do smth
else
printf("now i'm there\n");
//do smth else
}
How can I keep it simple and more universal?;)
Putting printf in every if-else pair seems unreasonably bulky...

This is usually a job for a debugger, most of which allow to step through the code one statement at a time. They also allow you to set breakpoints to pause execution at specific locations, watchpoints that pause execution when a variable changes, etc.
Without knowing your environment I can’t recommend a specific debugger to use. If you’re building code with gcc, then the companion debugger is (usually) gdb. You will need to use the -g flag when compiling to enable source-code level debugging. It’s not the friendliest debugger to use, but it’s pretty comprehensive. If you’re building in the Visual Studio environment on Windows, there should be a debugger as part of the IDE.

If you are using an IDE for purpose of writing code then it would have built-in facilities for debuggers, the only thing you would need to do is set break-points and then when the program is run your code would pause whenever a break-point is hit. IDEs also provide facilities to look up variable values at that instant.
If you are not using an IDE and your question is specifically w.r.t C you could consider using GDB. Have a look here to get a better idea of how to use GDB to debug programs.

There is nothing wrong using printf statements to track or log program flow for the purpose of learning, or testing during development. But a good debugger will probably serve the purpose just as well without having to add in-line code.
Depending on your environment there is a large list of debugger options available.
Following is an overview of debugging programs:
A debugger is a program that allows you to step through another
program one line at a time. This is very useful when trying to
identify incorrect code and analyze how a program "flows". Key
concepts include: Breakpoints, Stepping, and Viewing data.
Key things that you can use the debugger to determine are:
The flow of the program (what happens next on a line by line basis)
The creation of variables
The data being stored in each variable
The entering/leaving of functions
The calculations that are made
The entering of IF statements or ELSE statements
The LOOPING of code.
Much more detail here

Related

The console window of VScode(visual studio code) closes immediately

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a;
scanf("%d", &a);
printf("%d", a);
system("pause");
return 0;
}
Using the 'scanf', the console does not open properly. The visual studio code is too difficult. This is the first code. Please help me set the environment.
Does it answer your question?
system("pause"); - Why is it wrong?
Using system("pause"); is Ungood Practice™ because
It's completely unnecessary. To keep the program's console window open
at the end when you run it from Visual Studio, use Ctrl+F5 to run it
without debugging, or else place a breakpoint at the last right brace
} of main. So, no problem in Visual Studio. And of course no problem
at all when you run it from the command line.
It's problematic & annoying when you run the program from the command
line. For interactive execution you have to press a key at the end to
no purpose whatsoever. And for use in automation of some task that
pause is very much undesired!
It's not portable. Unix-land has no standard pause command.
The pause command is an internal cmd.exe command and can't be
overridden, as is erroneously claimed in at least one other answer.
I.e. it's not a security risk, and the claim that AV programs diagnose
it as such is as dubious as the claim of overriding the command (after
all, a C++ program invoking system is in position to do itself all
that the command interpreter can do, and more). Also, while this way
of pausing is extremely inefficient by the usual standards of C++
programming, that doesn't matter at all at the end of a novice's
program.
So, the claims in the horde of answers before this are not correct,
and the main reason you shouldn't use system("pause") or any other
wait command at the end of your main, is the first point above: it's
completely unnecessary, it serves absolutely no purpose, it's just
very silly.

Stata: Call a do file containing loop from a program in the other do file

I am trying to call a do file which has loops from a program in other do file. I am getting an error.
Now, if I use do instead of include, it runs fine but I don't get to use local macros created. I used include so I can use the macros further in the program. I don't want to use global.
First do file (test.do).
forval i = 1/5 {
local val`i' = `i'
}
Second do file(call-test.do)
capture program drop test
program test
include "test.do"
di `val1'
end
test
I got error r(9611);
I using version 16.1
Response from Stata support
The -include- is designed to let you share definitions. It will not
work correctly within a program as documented in -help include-
The short answer is that -include- is usually ok to use in programs,
but not with looping commands, and if you use -include- in a program,
it probably isn't working the way you think it is.
Here's the long version of exactly what is going on:
When you use -include- in a program, your program literally includes
the -include- command in it. The program does NOT have the contents
of the include file substituted in place. That's the start of the
problem for looping commands.
In any case, when a program executes the -include- command, Stata gets
confused about whether to define a loop program on the behalf of a
looping command globally or within the program, and things go downhill
from there. Given how the code is structured, it is unlikely we could
fix -include- to behave differently, so our documentation really
should simply recommend against using -include- in programs. In
addition, at the point at which the failure occurs, Stata simply knows
that it cannot call a program that it thinks should already be in
memory, hence the 9611 return code. It has no idea at that point that
this was because it was called with -include-, unfortunately.
We could in the future introduce a true C-like "#include" for use in
programs which would simply substitute in-line the lines from whatever
was included into your program

Static variable doesn't initialize to given value

I have a static "init" variable to run a function once on startup, (RTOS) but it seems to initialize to a random value. If I remove the static tag, everything works great. (Except for the obvious issue of it running the init function every pass.) Could anyone give more insight as to why this isn't working or perhaps a better way to achieve this?
Example code:
void ManageStructures()
{
// Variable declarations/definitions
static uint8_t StructInitialized;
// Have also tried "static uint8_t StructInitialized = 0", neither worked
// Function prototypes
void InitStruct();
if (!StructInitialized)
{
StructInitialized= 1;
InitStruct();
}
Test = StructInitialized;
edit: I apologize for the lack of information. This is for a company and I am trying to stay within the bounds of our public information policy. The MCU is a STM32F7 series using the "Ac6 STM32 MCU GCC" toolchain. I am not well versed in compiler operations so it may take me longer to find answers to the compiler or makefile related questions.
edit: It has become clear that this is an issue with the compiler or linker scripts and not my code. That being said, it has also become abundantly clear that I need to learn more about toolchains, linker scripts, and compilers in general before getting to the root of this issue. I'll return to this question once I have become familiar enough to give valuable feedback or answer it myself. Thank you everyone for the feedback and direction!
It is common that embedded systems run with a "minimal startup" code, meaning that they never initialize .bss or .data during start-up. Meaning that if you write something like static int foo = 42;, the code will compile but the variable will never be set.
This isn't standard C compilant, so usually upon project creation you get an option from the IDE to have a "minimal" or "standard" startup.
This likely lies in the so-called "CRT" (C run-time) delivered with your tool chain and not in the RTOS. If you single step your program from where it actually starts (the reset vector) rather than from where main() starts, you'll be able to see exactly what the CRT does and doesn't.
Unfortunately debuggers often use a "dumbed-down mode", since embedded systems programmers are by default assumed to be completely incompetent nowadays. Meaning that they silently insert a breakpoint at main() and run until that point. You might have to "un-dumb" your debugger in order to debug the CRT.

Is it possible to add a getchar(); equivalent to a .o file?

I created a simple C program a while ago. It's a simple command-line generator that takes some number, prints the results and stops. I always ran it in the editor's command line enviroment that automatically paused after the program ran, so I omitted adding a getchar() at the end.
I now regret this, because I managed to lose the source. All I have now is the complied .o and .exe file, and the latter - of course - exits immediately after it prints the output, so it's unusable. It wasn't that long, about 100 lines, but I'd like to avoid rewriting it. (Also, I might even learn something new from this way.)
Now I have very basic knowledge of C, and about zero on computer-degree x86 assembly (though I learnt the basics of 8086-assembly for microcontrollers, it won't be that helpful now I guess), so I'm kinda stuck here. Can I either add that getchar() like pausing function to the complied code, or is there any way I can make that .exe stop before exiting while still keeping it standalone?
The program will run on a Windows 10 system.
I would write some sort of batch script in which you call your program and then just run pause, which waits for you to hit a key before it continues.
wrapper.bat:
yourprogram.exe
pause
Of course you can disassemble your executable into raw x86 assembly code, then look up the code for a simple getchar() on Windows, add that and reassemble. However, it would probably be less time consuming to rewrite the program, depending on how complex it was or just create a wrapper batch-script.
It's possible to hijack .o file, you can even do it with .exe, .dll, ... but it's not simple and requires a lot of know-how. What I would suggest is to use some sort of decompiler to try to restore the original source code, make the change and compile it again. You can find suggestions of decompilers in this old answer.

Can anyone suggest a way to trace every call of a function?

I want to trace each path of function calls.
For eg:
int a()
{
b();
return 1;
}
void b()
{
}
int main()
{
int x=a();
return 0;
}
So my call trace is main->a->b
In this manner I want to trace each set paths of calls.
I have thought of a depth first search. But i am not sure how this would go.
Can anyone suggest me any concrete method to be implemented in perl?
I will have C program file and will run a perl script over it to get call traces.
There are a number of free call-graph programs listed in this article, including egypt which is a small Perl script that uses gcc and Graphviz to generate the static call graph of a C program.
One way is automatically instrument the source code with probes that collect the information you want as the program runs. You can use a program transformation tool to do that.
Here's a paper on how do collect information abouth "which blocks" get executed, using a transformation system to insert such probes. A very small change to the specification of where to put probes, and some minor work to capture the current function would accomplish what you want in a relaible way.
I believe Doxygen can do just that.

Resources