Saturday, June 09, 2007

Solving pesky LNK2005 errors...

For those who read this blog and aren't technically inclined or simply don't use Microsoft Visual Studio (e.g. you use a different compiler suite), this entry isn't for you.

One of most annoying things to run into in Visual C++ are linker errors. They are obtuse, poorly documented, and double-clicking them doesn't take you to the source code (or the part of the object file) where the problem is occurring. One of the most confounding error messages is the LNK2005 error message. Usually something like this shows up:

nafxcwd.lib(afxmem.obj) : error LNK2005 ...something about operator new/delete goes here...

If you search Google, a Microsoft Knowledgebase (KB) article pops up (KB148652):

http://support.microsoft.com/kb/148652

A lot of people run into LNK2005 errors, find the above article, try out what it says, and discover the "solution" makes the problem worse, not better. That is the only KB article I've ever seen that provides an incorrect solution for a problem...usually Microsoft is pretty good about giving right answers.

There are four causes of LNK2005 errors that I've run into and actually fixed:

1) A bad build. For some reason or other VS just occasionally barfs. The solution in this case is to close down VS, wipe all the temporary files (e.g. .obj, .dll, .exe, autogenerated MIDL .c files, etc.), load up VS, and do a Build->Clean Solution, Build->Rebuild Solution. Depending on the size of your solution, this can take a while - go grab a coffee.

2) If it still fails with LNK2005 errors, then something is mismatched. Right-click on each of the projects and select "Properties...". Then make sure the "'C++'->Code Generation->Runtime Library" all say the exact same thing. If you attempt to use different runtime libraries, it may or may not link properly. The reason it will not link is if you allocate memory in one project and then pass it to another project and free it there (sort of like DLLs but weirder). If you are like me and have projects shared between solutions, you will want multiple project compilation types so that you don't have problems with linker errors (I have 6 of 8 possible for my base library - the base library is multi-threaded - I say 8 possible because you have /MD[d] with MFC, which is different than /MD[d]). Once you have types matching (don't forget to match the "use MFC" option if you use MFC!), make sure both debug and release mode are configured correctly with the configuration manager (Right-click on "Solution 'solutionname' (x projects)" and select "Configuration manager..."). Also, make sure the dependencies and build order are correct (same right-click menu but "Project dependencies..." and "Project build order..." instead).

3) If you've done all that and still get LNK2005 errors, then you've hit a scenario I like to call the "duh" scenario. An incorrect entry point for the subsystem selected will raise a LNK2005 error message. So, if you defined main() and don't use /SUBSYSTEM:CONSOLE, you'll get a LNK2005 error. Or if you defined WinMain() and don't use /SUBSYSTEM:WINDOWS, you'll get a LNK2005 error. Again, this doesn't always happen, but when it does it is weird (usually complains about new/delete duplications across object files instead of main()/WinMain()). To change the subsystem, right-click on the startup project and select "Properties...". Then go to Linker->System->SubSystem. Change accordingly to the entry point used.

4) If, even after all that you still get LNK2005 errors, then it is time to scratch your head and think, "Gee, did I or any third party put in any include files that force .lib files to be included in the linking stage?" Start scouring that source code for any #pragma comment(lib, ...) statements. This happens particularly with MFC libraries since there is code floating around out there that forces the MFC libraries to be linked in at link time first and then forces the other libraries to be excluded - including such code with a non-MFC project causes all sorts of headaches since the other libraries are loaded first and thus can't be excluded by the #pragma and then the MFC libraries attempt to get linked in and fail. But it can happen in other cases as well - even indirectly via a third-party library.


I've never experienced this, but according to what people say on the Internet, when they run into LNK2005 errors, they completely rebuild all of the projects in their solution from scratch (i.e. brand new .sln and .vcproj files). It would take me several days to do that, so that is not an option for me. But apparently it can work. My guess: They implicitly did #1 and #2 by taking that approach - only it took way longer than necessary.

A lot of people suggest turning on /VERBOSE in the linker options. In my experience, that rarely helps to do anything but create more confusion. The option exists, so it is probably useful in some cases.

25 comments:

  1. I have the same problem. I want to try the first alternative you have given. Can you say what are all the places that I need to look for this temporary files. Also I did not understand the second option, I have only project to compile and I am getting error with VS libs. So what should I do now?

    ReplyDelete
  2. Actually I solved the problem. Some one had some linker options already in place. So your option number 2 works !

    ReplyDelete
  3. allrounder - Excellent! I just updated the blog entry with something new I encountered while performing an upgrade cycle to VS 2008.

    Your first post tells me that this page isn't quite geared for newbies. I've re-read the article and it seems that I made a lot of assumptions. I'll have to remedy that somewhere along the line.

    ReplyDelete
  4. Hey, I just want to say thanks for this post, you helped me out tremendously!

    Option #2 was the one that fixed it for me.

    Thanks again!

    ReplyDelete
  5. I ran into a LNK2005 today. The above suggestions are good and valid. But I might offer one more: the LNK2005 I had today was due to some C++ code from a vendor library that failed to use the static keyword on a declaration within a header file that is intended to be a global.

    e.g.
    Some_type some_global_data(1,2,3); // defined outside a class body, etc.

    Adding the "static" keyword before this declaration fixed my LNK2005 problem. And, my apologies if this was actually already suggested and I just missed it.

    ReplyDelete
  6. thanks voidstar, that comment helped me

    ReplyDelete
  7. Thanks your option #2 helped me out. I have explained how i solved it more clearly. I had two base library one of them C++>code generated using MDd and the other one using MTd. I regenerated both of them using one option which i used for my project and the linker error got sorted.
    Thanks once again.

    ReplyDelete
  8. Thanks for this advice. Option #2 fixed my problem. I spent about 4 hours trying to figure this out before I stumbled on your page. Thanks!

    ReplyDelete
  9. Just like the other commenters, option #2 fixed it for me too. Thank you SO much. This post's getting bookmarked pronto! :)

    ReplyDelete
  10. ========== Build: 2 succeeded, 0 failed ...
    Nuff said. Thanks for the help!

    ReplyDelete
  11. Or it could be that the code has an #include "____.cpp" (hooray for grading an intro to C++, I'm actually learning a lot)

    ReplyDelete
  12. Thanks a ton Thomas. opt#2 worked out for me! I was stuck on the link error for hours!! your blog page helped me fix it. thanks for your wonderful work.

    ReplyDelete
  13. Thanks Thomas!!

    Your advices are great. I struggled with the same problem all day, and option #2 solved the problem for me. Keep up the great work!

    ReplyDelete
  14. I'm still struggling with this problem! I've tried the advice given but I did notice when this error occurs for me.

    For example, say I have program.cpp and program.h and a use_program.cpp

    use_program.cpp has a: include "program.h" and program.h has a: include "tools.h"

    tools.h is composed of function definitions, so there is no separations of function body and header. Every function in tools.h will have the LNK 2005 error. When I separate tools.h into a .cpp and .h file, then the functions work fine.

    I tried another test where I have a: include "something.h" that works perfectly fine (only has struct definitions) and included a single function definition in something.h. Before, my program was compiling fine (I left out the include tools.h) and with the new function addition, that is the only function that gets the error... help anyone?

    ReplyDelete
  15. Good all rounder, except one thing.

    When writing C++, you need to have everything inside a class or a function. I was writing a C program and got LNK2005 and I couldn't understand the problem. The thing was VS was compiling the code as C++, which doesn't allow variable definitions in .h files.

    Project propertise -> configuration properties -> C/C++ -> Advanced -> Compile As to Compile as C Code fixed my problem. That or encasing the variable in a class aka. actually write C++ code =P

    ReplyDelete
  16. You rock. #2 did it. What an unhelpful error description...

    Thanks!

    ReplyDelete
  17. I struggled for awhile with KB148652 which, as you say, is confusing. Your #2 above helped solve my problem. Thanks!

    ReplyDelete
  18. @Ale - I love how the #2 solution solves most people's problems with this particular linker error. If I had known that when I wrote this article, I would have made it the #1 solution. :)

    ReplyDelete
  19. From http://msdn.microsoft.com/en-us/library/72zdcz6f(vs.71).aspx :

    A header file declared and defined a variable. Possible solutions include:
    Declare the variable in .h: extern BOOL MyBool; and then assign to it in a .c or .cpp file: BOOL MyBool = FALSE;.
    Declare the variable static. (THIS WORKED FOR ME)
    Declare the variable selectany.

    ReplyDelete
  20. You also get similar errors if you make the mistake of doing #include ".cpp", instead of #include ".h", as I just found out with an hour's hacking. This should be a 5th case.

    ReplyDelete
  21. Hello Thanks for the great post , I may have figured another thing that cause this LNK 2005 error .

    The Project consist of (treap.h and main.cpp) , and in the class treap .h file I declared "ymax" a static variable , then give it a value like this (int treap::ymax =0; after the class ending brackets {}; ) , but I moved the line to the main.cpp file and put it before main() and did a clean and then rebuild then it works like magic .

    Am i right ? or i shouldn't put that line in the .h file in the first place .

    thanks

    ReplyDelete
  22. Consistently, this is why I get a LNK2005.

    I declared and defined a function in the .h file.
    I included the .h file elsewhere in my solution.

    Fix:

    Declare the function in the .h file.
    Define it in an appropriate .cpp file.

    ReplyDelete
  23. Declaring variable as static worked for me. Thanks guys.

    ReplyDelete
  24. Thanks option 2 worked for me.

    ReplyDelete