Reputation: 51
I am looking a tool able to detect ordered function call pairs in a nested fashion as shown below:
f() // depth 0
f() //depth 1
g()
g()
At each depth of call f()
there must be a call of g()
forming function call pair. This is particularly important in critical section entry and exit.
Upvotes: 5
Views: 220
Reputation: 239261
The Coccinelle tool for semantic searching and patching of C code is designed for this sort of task (see also this LWN article on the tool).
Upvotes: 0
Reputation: 78963
You may abuse a for
-loop for this.
#define SAVETHEDAY for (bool seen = ((void)f(), true); seen; seen = ((void)g(), false))
The comma operator always lets your functions f
be executed before the dependent statement and g
afterwards. E.g
SAVETHEDAY {
SAVETHEDAY {
}
}
Pros:
for
-loop will be
optimized away by any decent
compiler.Cons:
break
, return
and continue
inside the blocks, so g
might not be called in such a situation.throw
inside, again g
might not be calledThe problem with continue
can be repaired by doing things a bit more cleverly.
The first two cons can be circumvented in C++ by using a dummy type as for
-variable that just has f
and g
in the constructor and destructor.
Upvotes: 2
Reputation: 490518
Scan through the code (that's the hard part) and every time you see an invocation of f()
, increment a counter. Every time you see an invocation of g()
, decrement the counter. At the end, the counter should be back to zero. If it ever goes negative, that's a problem as well (you had a call to g()
that wasn't preceded by a matching call to f()
).
Scanning the code accurately is the hard part though -- with C and (especially) C++, writing code to understand source code is extremely difficult. Offhand, I don't know of an existing tool for this particular job. You could undoubtedly get clang (for one example) to do it, but while it'll be a lot easier than doing it entirely on your own, it still won't be trivial.
Upvotes: 0
Reputation: 355217
In C++, one option is to wrap the calls to f()
and g()
in the constructor and destructor of a class and only call those functions by instantiating an instance of that class. For example,
struct FAndGCaller
{
FAndGCaller() { f(); }
~FAndGCaller() { g(); }
};
This can then be used in any scope block like so:
{
FAndGCaller call_f_then_later_g; // calls f()
} // calls g()
Obviously in real code you'd want to name things more appropriately, and often you'll simply want to have the contents of f()
and g()
in the constructor and destructor bodies, rather than in separate functions.
This idiom of Scope Bound Resource Management (SBRM, or more commonly referred to as Resource Acquisition is Initialization, RAII) is quite common.
Upvotes: 11