10

I have a large application written in C + POSIX there are many functions which are never called inside it. However, due to the size of the code it is difficult to track them manually.
Some people have suggested to use gcc with-Wunusedand lto, but it didn't returned any used functions, whereas I continue to find and remove some manually.

So I think I need a code coverage tool for analysing the program at run-time. Peoples suggested me gcov or valgrind, but I was unable to find how to use them to print a list of dead functions. gcov alone revealed only 68% of the functions compiled are used, but I don't have any way to list them.

So does someone know a good tool, and if so tell me how exactly I can use it for that purpose (a command line example would be welcome)?

I removed all functions which are not used in the source code. Only functions like this remain inside the source code :

if(conditional statement) {
    some stuff;
    dead_function();
    some_stuff;
}

Whereconditional statementis never true at run time, and the removal ofdead_function()would lead to the removal of the statement to avoid undefined errors.

  • 1
    So what you're looking for isn't actually unused functions (dead_function is used) but dead code. That requires completely different techniques! Beware that runtime analysis will only find code that doesn't happen to have been run in a particular execution of the program — that code may be live under different circumstances. – Gilles 'SO- stop being evil' Jun 23 '14 at 11:19
  • @Gilles : that's kinda the problem of gcov... How to combine the result of different launch? I have for the parameter. That's said the program does only one things : finding very large primes, so it easy to test all cases. This is also why I try to remove dead code (performance critical). – user2284570 Jun 23 '14 at 21:52
  • It appears you don't want dead function removal, but rather dead conditional code removal. Do I have that right? – Ira Baxter Jun 24 '14 at 6:08
  • 1
    Bear in mind that code that is never called has very little impact on performance other than loading time and memory footprint. To aid with both move as much of your code as possible into a lot of small DLLs or .so shared libraries - those that are never actually used will never be loaded. If you are having severe performance issues you probably have code that is called but the results are never used - lint can help find those. – Steve Barnes Sep 16 '14 at 5:04
  • 1
    @Mawg I don’t use jump tables directly. Maybe the compiler can generate some automatically, but I don’t use them. – user2284570 Sep 20 '18 at 17:06
3

Given that @user2284570 is in the comfortable situation of covering 100% of use cases via tests dynamic code analysis will provide the answer. In other cases removal of functions, their calls and conditions would require a thorough review.

Any code coverage tool will report function coverage in one form or the other. The main gripe seems to be reporting of the exact location of unused (here: dead) functions. I cannot speak for other tools but our company's has a text format reporting option that features placeholders for source file name and line data. Since a concrete command line example was asked for here's one:

$ csgcc -o myapp mycode.c
$ ./myapp --run-all-tests
$ cmcsexeimport -m myapp.csmes -e myapp.csexe --title=mytests
$ cmreport --function-coverage -m myapp.csmes --format-unexecuted='%f:%l'

This will print the dead function locations like:

mycode.c:101
mycode.c:213
mycode.c:1032

A local university student wrote up more detailed instructions for this approach.

After eliminating unused functions you'll also want to analyze Branch Coverage and removed superfluous if() statements and others. Just beware of side effects of evaluated expressions. But luckily, your perfect code coverage will detect regressions.

  • 1
    I must say I ended up using step by step manual debugging since that time for removing dead code. So I won’t try your tool. – user2284570 Sep 20 '18 at 17:09
4

You can use splint with the alluse flag to check for unused functions but personally I would use doxygen to produce a call map - any functions that have no parents are probably unused - just look out for any functions that are in tables of functions that might not be directly called but things like state machines might invoke from the table index.

Doxygen is an invaluable tool for dealing with large code bases and is well worth learning how to use in any case, it is free and available for multiple platforms, it also tends to encourage documenting your code as you go.

In the case of code that is called but only from unreachable code you will have to use a full static analysis tool like LDRA, (costly), that will point you to unreachable code. In this case it is better to remove all unreachable code first then look for uncalled functions. Alternatively you will need a test suite that you are sure exercises 100% of the functionality - then you can use a profiler or coverage tool like gcov on your program while running your test suite. If your test has exercised all of your functionality and you have portions with 0% coverage then they are uncalled but you will then have to find the calls to them that are unreachable and remove that code for the linker not to complain anyway.

  • "You can use splint with the alluse flag" I still don't understand.. can you provide a command line example? For doxygen, the answer is No! I just finished to remove every functions which don't have been used in the code. Only remain those who are used in the code but where some conditional statements make them never called at run time. and a call map can't help with hundreds functions. I definitely need a readable output with uncalled functions sorted out and with the file-names and line numbers of the area at which they are declared. – user2284570 Jun 22 '14 at 13:36
  • Steel no detailed example... So I don't understand what I can do... – user2284570 Jun 22 '14 at 14:52
  • 3
    @user2284570 This answer is correct for the question as you originally posted it. You shouldn't change questions in a way that invalidates answers! It would be better if you reverted your “Update” edit to the question and asked a new question instead. – Gilles 'SO- stop being evil' Jun 23 '14 at 11:20
  • Beware, of course, of functions which are called by function pointer, such as callbacks and state/event jump tables. – Mawg Sep 22 '15 at 11:57
  • @Mawg there weren’t such functions. – user2284570 Jan 3 at 1:26
1

To answer your revised question - if you compile all your code with gcc -fprofile-arcs -ftest-coverage options set and then run a suite of tests which you are sure covers all the functionality and all the possibilities, (possibly across several runs).

The gcov utility does expect you to do some of the work - it doesn't simply have an option for "tell me what didn't get called" so you will have to find those functions that didn't get called.

You can use gcov with the --function-summaries option on each source file you will generate a set of output files which will include function summaries - look for any of those that include either never or 0% to find the un-executed functions.

I would suggest either adding a function that you know will never be called or knowing about one that you haven't removed yet - this will let you see what the output looks like - you can then use grep to find them all.

Your next step will be to use grep or something similar to look at the gcov output for all the places that those functions are present in your code - you should see execution counts of 0 for the entire branch containing the call this will give you a good starting point for either extending your tests - for use cases that you had missed - or for code removal.

  • Then, It exactly can't do what I need : sort out unused function and tell the lines along file paths. It is the same I did with kcachegrind before posting this question. Sorting out function manually is and greping to find them is OK , but it isn't if you have a lot. – user2284570 Apr 30 '15 at 13:43
  • I guess you will have to hire someone who can code to do it then! Tools will not do the lot for you otherwise you would be redundant. – Steve Barnes Apr 30 '15 at 15:12
  • I don’t need something for automatic removal. I need something which can list unused function at run time without used function in that list. I also need their declaration path. Also I’m doing this for myself. So expect it that I won’t write my own answer for some years. – user2284570 May 1 '15 at 14:51
  • Steel unable to automatically sort unused functions out of called ones… In the meantime, I realised the computing requirements for generating secure random primes fitting on 65Ko. – user2284570 Sep 22 '15 at 23:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.