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?

Alex Feinman
  • 5,792
  • 2
  • 27
  • 48
Jamie Taylor
  • 480
  • 1
  • 4
  • 12
  • 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. – thorsten müller Sep 23 '13 at 09:48
  • @thorstenmüller Ah, yes. Sorry, I was using the term 'compiler' to refer to the entire compilation tool chain. – Jamie Taylor Sep 23 '13 at 09: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 Sep 23 '13 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. – Jamie Taylor Sep 24 '13 at 10:02

2 Answers2

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.

ratchet freak
  • 25,706
  • 2
  • 62
  • 97
  • So in my example oldFoo is dead code and, as such, the compiler and linker would be able to flag it as dead code, if the tool chain I'm using supports dead code detection? – Jamie Taylor Sep 23 '13 at 10:28
  • 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? –  Sep 23 '13 at 14:24
  • @MichaelT but a private method can only be called by methods within the class itself, right? So if a private method is included in the compiled library that is not pointed to by anything... – Jamie Taylor Sep 23 '13 at 15:36
  • 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 – ratchet freak Sep 23 '13 at 15:38
  • 2
    @JamieTaylor From SO - [How to access private methods and private data members via Reflection?](http://stackoverflow.com/questions/11483647/) or if you want to abuse cpp for C++ or other options [Calling private method in C++](http://stackoverflow.com/questions/6873138/calling-private-method-in-c) –  Sep 23 '13 at 15:39
  • @MichaelT Wow! I did not know that you could call private methods like that. I'd better go put some extra security in some of my old code. Thanks for pointing that out. – Jamie Taylor Sep 23 '13 at 15:45
  • @JamieTaylor Before going too far down that path - why is it important? Does it cost more than its worth (getting the stack from a thread can be expensive)? –  Sep 23 '13 at 16:20
  • 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 Sep 23 '13 at 17:01
  • 1
    @JamieTaylor before you defend your code against reflection read http://programmers.stackexchange.com/questions/101351/ – ratchet freak Sep 24 '13 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).

gbjbaanb
  • 48,354
  • 6
  • 102
  • 172
  • 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? – Jamie Taylor Sep 23 '13 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 Sep 23 '13 at 15:39