static analysis - how to simply detect assignment statements in C - c

I want to write a script that verifies there are no assignments of certain global variables. Say I have all my global variables initialized in files specifically for that, and that I don't want to pass these files into my script.
For example, I want to verify there are no assignments in any of my global variables that start with X_.
int var1 = 5; // that is fine
int X_global_var1 = 10; // error
How do I detect that without reinventing the wheel? is there an easy way in Python?
It is not simple as it sounds because there might be more cases like == and if the variable is a pointer to data then *X_global_var1 = 2; is legal too..
For encountering code comments for example, I use Comment Parser python package, with a C language flag and it works great. Looking for something similar for assignments.

Related

How to reduce dependence caused by global variables in c program

I want to speed up the processing of a sequential C program using multi-threading. My problem is that my C program has a lot of global variables. They are read and written by the functions in my C program. Therefore, it is prevented to parallelize functions together by multithreading because it no longer holds the exact result compared to running sequence programs.
I using OpenMP to handle my C program. However, I wanna refactor my C program to react above purpose before use OpenMP
Here my example:
int a = 5 ; // global variable
funcA () {
int b;
b = a + 5; // read a
}
funcB () {
printf("%d\n", a);
}
I don't wanna find the way to parallel complete funcA and funcB but I want reduce the dependency caused global variable (like variable a in above example).
There is no simple way to do a complicated thing. It can seem difficult sometimes to design a code without global variables even when coding from zero. I your case, the problem is significantly more difficult.
There is not (and cannot be) a generic solution about how to minimize the number of global variables.
The only thing which can be done is:
analyze the code base;
understand the purpose of the global variables and how they are used;
find a way to achieve the same behavior without using global variables.
Of course, it might be easier for some global variables to be dealt with than others. You may want to start with the former. Seeing success coming your way will help your morale during the task.
It might help you if you read about how to make code:
tread safe;
re-entrant.
Google can help you greatly on this.
In general it is not an easy task to remove global variables.
You need to go on a case by case basis.
What you really need to do is to try to pass the variables required as function parameters rather than having them as globals.
In this example given, i cannot give any solution without looking at how the functions funcA and funcB are called. You should try to pass the variable a as a parameter to both the functions. You may need to go back up a few functions until you get to a common function which ultimately calls both functions.

How to check if a variable has been initialized in C?

Is there a way to check if a variable has been initialized or not in C?
Consider the following example,
int main(){
int a = 3, b = 7, c;
if ( a > b )
c = a-b;
// Now, how can I check if the variable "c" has some value or not
// I don't want check like this,
// if ( isalpha(c) ) or if ( isdigit(c) )
// or anything similar to like that
}
In other words, does C has some function like defined in Perl. In Perl, I can simply do if (defined c)that would check if the variable is defined or not, and it'd return False for above example. How can I achieve the same in C?
C does not have this ability. You have two main options:
A sentinel value
For example, if you know that the value of c will never be negative, then initialize it to -1, and test that for that.
Add another variable
Create another variable bool we_set_c_to_something = false; and then set it to true when you write to c.
C is a compiled language which doesn't support runtime variable binding, while Perl is a interpreted language which support dynamic typing. So you can check the definition of a variable in Perl, but not in C.
When you declare a variable in C int c;, this variable c is defined but without initialization. The declaration and definition are in one statement.
The definition of a variable in C is not checked by code writer. The compilers do it for you. When compile and link your C code, the compiler will check all variable's definitions. An error will be invoked and the compiling or linking process will stop if there are undefined variables found in your code.
Hope this will make you distinguish the differences.
Wrong question. You're not asking whether the variable is defined. If the variable is not defined then compilation fails. Look up the difference between "declaration" and "definition". In the case of those local variables, you have defined the variable c.
What you're looking for is initialisation. Many compilers will warn you about using variables before they're initialised, but if you persist in running that code then the assumption is that you know better than the compiler. And at that point it's your problem. :) Some languages (e.g. Perl) have an extra flag that travels along with a variable to say whether it's been initialised or not, and they hide from you that there's this extra flag hanging around which you may or may not need. If you want this in C, you need to code it yourself.
Since C++ allows operator overloading, it's relatively easily to implement this in C++. Boost provides an "optional" template which does it, or you could roll your own if you want a coding exercise. C doesn't have the concept of operator overloading though (hell, the concept didn't really exist, and the compilers of the day probably couldn't have supported it anyway) so you get what you get.
Perl is a special case because it rolls the two together, but C doesn't. It's entirely possible in C to have variables which are defined but not initialised. Indeed there are a lot of cases where we want that to be the case, particularly when you start doing low-level access to memory for drivers and stuff like that.

Using SWIG, dereference a C array pointer to a TCL variable

The scenario. I use a software (A) that allow me to use a TCL script (B). Since I have to do many operations In B, I build a C code (C) to use via SWIG and do the math. Now, I'm running A in parallel, and I'm able to use some built-in TCL-functions of A to send and receive some variable of B via MPI. The problem is that one of this variables is really a C array.
I know that SWIG interchanges only the memory address between the C and TCL, but to send this to another computers is useless. So I think that I have to dereference the array into a TCL variable.
Could someone give me an idea of how to do this?
PS: I don't know too much about SWIG.
typemaps are the way to go here. What they essentially allow you to do is to provide SWIG with code snippets that are added to the top and bottom of your wrappers. In other words, you can control how you parse arguments and how you clean up once your operation is complete.
From your explanation it is hard for me to tell what exactly it is you are trying to achieve. Maybe some pseudo-code would make things clearer. I am a user of SWIG with Python and know nothing about TCL, so I will try to explain how I'd do this with my setup.
Lets say this is the function being wrapped:
double[] foo_c (double bar[], int a_size);
You want the return value of the function to be "dereferenced". So you want the function to return not-a-pointer. In python, lets say I want the function to return a Python list.
typemap(out) double[] foo_c //signature of function whose behavior is to be modified
{
$result = PyList_New (a_size); //$result is what SWIG will return
for (int i=0; i<a_size; ++i) {
PyObject *o = PyFloat_FromDouble ($1[i]);
//$1 denotes return variable before SWIG wrapping goodness
PyList_SetItem ($result,j,o);
}
}
As you can see, most of the code is really in C/C++ so it doesn't matter that I took a Python example. You just need to have a look at the TCL/C API to figure out which functionality you will be needing for your purposes.
Hope this helps!

reuse C code in simulink

Is it possible that I call a c program from a stateflow chart, then I copy this chart, still in this same model, and execute both with out any conflict?
For example a C program like this:
int var; // var is global
int myfunction(int n)
{
var = var + n;
return var;
}
i mean, treat them like two different entities and won't mess up with global variable.
btw, also without rename the function in source code, I've got a big program :)
This is more a C - related issue.
If you are using the same C function that operates on a global, then yes, all calls to this function will operate on the same variable.
What you can do instead is make this variable local to each of the calling Stateflow states and then pass it to the C function. This way you should not have conflicts and be able to reuse your code.
It's also a good design choice since you otherwise are potentially hiding a state variable in the function i.e. outside of your state machine.

Indirect variables access in C not C++

is it possible to access variable value through other variable, as below
char var[30];
char buffer[30];
strcpy(buffer, "ABC");
/*variable var is holding the "buffer" variable name as string*/
strcpy(var,"buffer")
is there a way to access the buffer variable value "ABC", through variable var. ?
Not in any practical way in C, and you don't really want to anyway. Tying your program logic to the names of your variables is a horrible idea. Typically I see people attempt this when what they really need is some sort of collection type (and array, a map, whatever).
How about filling us in on the problem you are trying to solve with this?
Per your comment:
I need to have dynamic debug messages, I have a file which contain each function variables that I want to print.
Use stringification in a macro:
#define str(s) #s
int main() {
int bar;
str(bar) /* replaced by "bar" */
}
Not without significant boiler plate code. Variable names are eliminated at compile-time.
In theory, you could store a map from variable names to a pointer to a variable.
No, you can't. If you want indirect access, then declare a pointer and assign var to it.
char *forVar = var;
// Now you can access/modify via [] operator.
You can try using a union
For example:
union example {
char var[40];
char buffer[40];
} e1;
strcpy(e1.var, "ABC");
printf("%s is same as %s", e1.var, e1.buffer);
So basically you want to log some variables when they are written to/read from/passed to functions etc?
Doing this with compiled C is difficult, as mentioned, especially if you are optimising your executable (-0n on the compile statement), in which case some of the variables can disappear completely, or get re-used by other variables.
Using GDB
Having said that, I know gdb can log variable access and that sort of stuff. If you were to write a python script (see http://sourceware.org/gdb/onlinedocs/gdb/Python.html), you should be able to write a script to log variable content.
See this question for more: Do specific action when certain breakpoint hits in gdb
On demand only, using pre-compiler scripting
Alternatively, if you just wanted to do it on demand, you'd be better off using a pre-processing script to add in custom macro's or similar, using a csv file as input:
for each line in CSV:
read variable_name, file_name, variable_type
find all occurrences of variable_name in file_name
for each occurrence
insert printf(....)
On demand only, using macros
Good luck. There isn't a nice way to do it, because you'd generally need some sort of lookup, and you'd need a way of selectively outputting variables to your print function. In some cases you could do something like:
static char _LOGGED_VAR_001 = 'z';
static char _LOGGED_VAR_002 = 'z';
#define cMyVar _LOGGED_VAR_001
#define LOG_ALL_VARS() printf("Vals: %c, %c", _LOGGED_VAR_001, _LOGGED_VAR_002)
void myFunc()
{
char cMyVar; // Gets macro'd to _LOGGED_VAR_001 with LOCAL scope
cMyVar = 'a'; // LOCAL scope _LOGGED_VAR_001 becomes 'a'
LOG_ALL_VARS(); // At this point you print out the LOCAL _LOGGED_VAR_001
// and the global _LOGGED_VAR_002
}
You would get Vals: a, z
This is pretty ugly, would only work for variables with local scope, messes round with memory consumption, could be error prone and is generally a bad idea.
On demand, heap/stack dump
If you have enough storage, you could dump all your memory on demand to a file. This probably wouldn't be very portable, depending on how it was done. I'm not sure how to do it though, in a reliable manner.
Recommendation
Use GDB for design-time diagnostics. It's what it's designed for :)
For (e.g.) analysing released code (automated bug reports), a full dump and then analysis at will might be relevant.

Resources