问题
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.
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/32447978/odd-vs-name-mangling-behavior