1

[Potentially misleading title, but I'm not sure how best to word it.]

Theoretical question on compilers and language design.

Say I'm re-implementing a method in a code base. Instead of removing or commenting out the method that I'm re-implementing I leave it where it is, for reference and testing purposes, and just remove all the calls to it. Something like the following (in C-style pseudo code):

public void aMethodToCallFooVariants()
{
   // oldFoo();
   newFoo();
}

private void oldFoo ()
{
   // Some code here that's not very good
}

private void newFoo ()
{
   // Some better code here
}

newFoo is called by the method that originally called oldFoo, meaning that oldFoo is no longer called anywhere in the source code, but it still in the listing.

Are compilers smart enough such that when I run my build script, the code for oldFoo isn't included in the compiled binary, or will oldFoo still be included but not called anywhere? I can understand if public method will still be included, they could be called by code that is external to the compiled binary (especially if it's compiled as a library). But would the private method still be compiled into the binary?

4
  • 4
    I think that's more a linker issue and not the compiler. I'm rather sure that C and C++ with gcc would leave the code out. But this may actually depend on the language or even specific implementations of compiler and linker. Commented Sep 23, 2013 at 9:48
  • @thorstenmüller Ah, yes. Sorry, I was using the term 'compiler' to refer to the entire compilation tool chain. Commented Sep 23, 2013 at 9:51
  • 2
    Why would you not remove that method? All it does is pollute the class. This is what source control is for.
    – billy.bob
    Commented Sep 23, 2013 at 12:52
  • @m.edmondson I agree. I was just wondering whether incremental builds for testing the newer functionality would include methods that are not public and no longer called anywhere. Commented Sep 24, 2013 at 10:02

2 Answers 2

3

That depends on the compiler and linker and how well their dead code elimination works. It is important to note however that in a turing-complete language (with reflection) it is undecidable whether a certain piece of code ever gets reached (halting problem hard)

In other words if you use a source control press that delete button and leave a message in the commit and/or mention is in the documentation of the new method.

You can use a transition period where you mark the method deprecated and have the compiler issue a warning each time the old version is used.

9
  • 3
    @JamieTaylor but if its compiled as a library or object file, how do you know its dead and isn't used by something else that links to it? If the language has some form of reflection or introspection of code, how do you know that it isn't being discovered that way?
    – user40980
    Commented Sep 23, 2013 at 14:24
  • 1
    @JamieTaylor there are some heuristics with which you can say a method wasn't called but there will be holes anytime someone clever comes along Commented Sep 23, 2013 at 15:38
  • 2
    @JamieTaylor From SO - How to access private methods and private data members via Reflection? or if you want to abuse cpp for C++ or other options Calling private method in C++
    – user40980
    Commented Sep 23, 2013 at 15:39
  • 1
    I think in cases where a method isn't called directly, the compiler is perfectly within its rights to eliminate that code as part of its optimizations. If some other code wants to call it via reflection, then it's up to the developer to ensure that the particular optimization isn't used. Sort of like preventing code from being in-lined (which will also remove a method's entry point).
    – TMN
    Commented Sep 23, 2013 at 17:01
  • 1
    @JamieTaylor before you defend your code against reflection read programmers.stackexchange.com/questions/101351 Commented Sep 24, 2013 at 10:06
2

With C and C++ compilers, the answer is yes - when a code unit is compiled into object code (by the compiler) all functions are listed explicitly. The linker then takes each of these object files and resolves the references to the functions - and all the functions that are left over after this linkage step, can be discarded. This is especially useful for static libraries where you only want a small part of the lib to be included, the rest is ignored and not linked into the final binary.

(obviously this doesn't happen for dynamic libraries, in this case the stubs that are present in the import library are not linked in).

2
  • That makes sense. I mean, say you include the std but only call cout, you don't want all of the other code from std included in your binary. Right? Commented Sep 23, 2013 at 15:37
  • 1
    That's right. Smaller binary = better performance, load time, etc. In C++ you famously "only pay for what you use".
    – gbjbaanb
    Commented Sep 23, 2013 at 15:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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