58402

Odd VS name mangling behavior?

Question:

Consider the following do-nothing code, which I am compiling as C++ on Win10 64-bit:

int test(int argc, char *argv[]); int main(int argc, char *argv[]) { return test(argc, argv); } int test(int argc, char **argv) { return 0; }

If all of this code is placed in the same .cpp file it compiles and links correctly in VS2012, VS2013, VS2015, and mingw32-g++ v4.7.1, as I would expect it to.

However, if I simply move the definition of the test function into a separate file the resulting two files still compile and link correctly with the mingw compiler but on all versions of VS I get:

error LNK2019: unresolved external symbol "int __cdecl test(int,char * * const)" (?test@@YAHHQAPAD@Z) referenced in function _main"

I can resolve this problem in VS by simply changing the declaration of parameter argv in the test function to char *argv[], but that shouldn't be necessary since char *argv[] and char **argv mean exactly the same thing when used to declare a parameter.

I haven't tried it but it makes me wonder if VS would also consider the two versions different for overloading purposes.

Answer1:

Yes, this is a bug in the Visual C++ name decoration scheme. For pointer-type parameters, top-level const and volatile qualifiers are encoded into the decorated name, even though they are not relevant to the type of the function. So, for example, char** and char** const are encoded differently. (In your example, char*[] is equivalent to char** const.)

When determining how to decorate the function name, the compiler will use the first declaration of the function, even if the definition does not exactly match the first declaration. This is why your example links when the definition is in the same source file as the main function: The test function is decorated with the name required by the first declaration, which is the same name that is referred to from within the main function.

If you move both the declaration and the definition into a separate source file, e.g.,

int test(int argc, char *argv[]); int test(int argc, char **argv) { return 0; }

then your program will also link successfully, for the same reason. This is why this "bug" is not usually a problem: Usually when functions are used across multiple translation units, they are declared in a header file and there is one declaration that is included everywhere.

Answer2:

For the separate file, use test(int argc, char ** const argv), based on the error message. Note that the address of an array (char * argv[]) would be constant (so argv would be constant), as opposed to a pointer to pointer (char **argv). Although since argv is passed by value, it can't be modified so I'm not sure why VS is being picky about this.

When both functions are in the same file, apparently VS can detect that test() does not modify argv, so it doesn't complain.

Recommend

  • error LNK2019 unresolved external symbol dbbind referenced in function
  • Error with vtkRenderer
  • LNK 2019 - Unresolved External Symbol
  • Clang Cross Compiling for Windows Phone ARM target
  • cmake MSYS Makefiles generator missing
  • Cannot open include file :'stddef.h' No such file or directory found error when creating a
  • Linking To V8 Snapshot
  • How do I compile a C/C++ program through windows command prompt?
  • XNU incudes in Kext
  • Retaining data after updating application
  • How to handle elastic beanstalk deployment so it uploads only changed files
  • How can I replace the server in Web Component Tester
  • Struts 2 TextField Tag with an attribute and no value
  • Salesforce Different WSDL files and when to use
  • Filter strings with regex before casting to numeric
  • NUnit 3.0 TestCase const custom object arguments
  • Groovy: Unexpected token “:”
  • How to define custom class, title, and target in Link Browser for content elements and the new rte_c
  • Webgrid not refreshing after delete MVC
  • VSO Build — Response status code does not indicate success: 404 (Not Found)
  • Jquery UI tool tip close icon
  • Read text file and split every line in MSBuild
  • Fetching methods from BroadcastReceiver to update UI
  • Does CUDA 5 support STL or THRUST inside the device code?
  • Statically linking a C++ library to a C# process using CLI or any other way
  • Build own AppleScript numerical error handling
  • Traverse Array and Display in markup
  • Proper folder structure for lots of source files
  • C# - Getting references of reference
  • Hits per day in Google Big Query
  • -fvisibility=hidden not passed by compiler for Debug builds
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • Qt: Run a script BEFORE make
  • Linking SubReports Without LinkChild/LinkMaster
  • Are Kotlin's Float, Int etc optimised to built-in types in the JVM? [duplicate]
  • XCode 8, some methods disappeared ? ex: layoutAttributesClass() -> AnyClass
  • Binding checkboxes to object values in AngularJs
  • Net Present Value in Excel for Grouped Recurring CF
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize
  • How to load view controller without button in storyboard?