Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
220 views
in Technique[技术] by (71.8m points)

c++ - LNK2001 error when compiling apps referencing STLport-5.1.4 with VC++ 2008

I apologize in advance for the long post...

I used to be able to build our VC++ solutions (we're on VS 2008) when we listed the STLPort include and library directories under VS Menu > Tools > Options > VC++ Directories > Directories for Include and Library files. However, we wanted to transition to a build process that totally relies on .vcproj and .sln files. These can be checked into source control unlike VS Options which have to be configured on each development PC separately. We handled the transition for most libraries by adding the Include directories to each Project's Property Pages > Configuration Properties > C/C++ > General > Additional Include Directories, and Library directories to Linker > General > Additional Library Directories.

Unfortunately, this approach doesn't work for STLPort. We get LNK2019 and LNK2001 errors during linking:

Error   1   error LNK2019: unresolved external symbol "public: virtual bool __thiscall MyClass::myFunction(class stlp_std::basic_istream<char,class stlp_std::char_traits<char> > &,class MyOtherClass &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > &)const " (?myFunction@MyClass@@UBE_NAAV?$basic_istream@DV?$char_traits@D@stlp_std@@@stlp_std@@AAVSbprobScenarioData@@AAV?$basic_string@DV?$char_traits@D@stlp_std@@V?$allocator@D@2@@3@@Z) referenced in function _main MyLibrary.obj   

Error   5   error LNK2001: unresolved external symbol "public: static void __cdecl MyClass::myFunction(class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &,long,enum MyClass::MessageType,int,class stlp_std::basic_string<char,class stlp_std::char_traits<char>,class stlp_std::allocator<char> > const &)" (?myFunction@MyClass@@SAXABV?$basic_string@DV?$char_traits@D@stlp_std@@V?$allocator@D@2@@stlp_std@@000JW4MessageType@1@H0@Z)  MyLibrary.lib   

This happens while linking and executable project to dependencies which are library projects. Curiously, this does not happen while linking the library projects themselves. Any ideas?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

As mentioned in other answers, this is a linker error and likely the result of the library and the application being compiled with different options. There are a few solutions on tracking this down already (one of them as the chosen answer, currently). These solutions will work. However, there are a few tools that will make your search much much easier.

For starters, understanding decorated names will help. Within all that garbage, you will recognise some things: The name of your function, namespaces, some class types you are using. All of those characters around them mean something to the compiler, but you don't need the compiler to tell you what they are.

Enter undname.exe:


undname.exe <decoratedname>
  • is a simple command line program that is in your VS bin directory.
  • takes the decorated name as it's first argument.
  • outputs a human readable format of the symbol.

Armed with that knowledge, you can now move on to finding a reasonable candidate for the mis-created symbol.

First off, you could edit your libraries in a hex editor, as suggested elsewhere. However, there is a much easier way to find the symbols.

Enter dumpbin.exe:


dumpbin.exe <switches> <library name>
  • is a simple command line program that is in your VS bin directory.
  • takes a set of switches and a library to apply them to.
  • outputs information from the library

The switch you will be interested in for your question is /linkermember. There are many other switches that can get you very interesting information, but this one will list out all the symbols in the library.

At this point, a little commandline savvy will serve you well. Tools like grep can really shorten your work-cycle, but you can get by with redirecting to a file and using notepad or the like.

Since I don't have your code or library, I'll contrive an example from TinyXML.

Assuming your error message was this:

Error   1       error LNK2019: unresolved external symbol "public: unsigned char __cdecl TiXmlComment::Accept(bool,class TiXmlVisitor *) " (?Accept@TiXmlComment@@ZBE_NPAVTiXmlVisitor@@@Z) referenced in function _main     MyLibrary.obj 

Having determined this is a function in the TinyXML, I can start looking for the mismatched symbol. I'll start by dumping the linkermembers of the library. (Notice the switch is singular, this always gets me when I type it from memory!)


>dumpbin /linkermember tinyxml.lib
Microsoft (R) COFF/PE Dumper Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file tinyxml.lib

File Type: LIBRARY

Archive member name at 8: /
4992E7BC time/date Wed Feb 11 08:59:08 2009
         uid
         gid
       0 mode
    B402 size
correct header end

    859 public symbols

    16292 ??$_Allocate@D@std@@YAPADIPAD@Z
    16292 ??$_Char_traits_cat@U?$char_traits@D@std@@@std@@YA?AU_Secure_char_traits_tag@0@XZ
    16292 ??$copy_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDI@Z
    16292 ??$copy_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDIU_Secure_char_traits_tag@1@@Z
    16292 ??$move_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDI@Z
    16292 ??$move_s@U?$char_traits@D@std@@@_Traits_helper@std@@YAPADPADIPBDIU_Secure_char_traits_tag@1@@Z
    16292 ??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z
    16292 ??0?$_String_val@DV?$allocator@D@std@@@std@@IAE@V?$allocator@D@1@@Z
    16292 ??0?$_String_val@DV?$allocator@D@std@@@std@@QAE@ABV01@@Z

This is obviously too much to read, but we don't have to, we know what we're looking for, so we'll just look for it.


>dumpbin /linkermember tinyxml.lib | grep Accept
    529AE ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlDeclaration@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlDocument@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlElement@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlText@@UBE_NPAVTiXmlVisitor@@@Z
    529AE ?Accept@TiXmlUnknown@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlDeclaration@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlDocument@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlElement@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlText@@UBE_NPAVTiXmlVisitor@@@Z
        3 ?Accept@TiXmlUnknown@@UBE_NPAVTiXmlVisitor@@@Z

That's much easier to read. Looking at our error, we're looking for the Accept Function of TiXmlComment. We could grep the output additionally for that name, if we had lots of matches (like looking at the size function in the stl!), but in this case, we can pick it out of the list. Here is where we turn to undname:


>undname ?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?Accept@TiXmlComment@@UBE_NPAVTiXmlVisitor@@@Z"
is :- "public: virtual bool __thiscall TiXmlComment::Accept(class TiXmlVisitor *)const "

So, in this example, our application is looking for a function which returns an unsigned char, but the library has a function returning a bool.

This is a contrived example, but it illustrates the technique to use to track down your issue. You are probably looking for a typedef type which is set differently based on your options.

The problem where I ran into this was with time_t. In some libraries I was using, the time_t used a 32-bit type as part of it's internal representation. This library was generated with an older compiler, where that was the default. In VS 2005, the time_t uses a 64-bit type by default. I had to add the preprocessor define _USE_32BIT_TIME_T to get it to compile. I tracked this issue down precisely as I have described.

I hope this helps someone solve this issue!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...