Odd VS name mangling behavior?
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.
c++ visual-studio-2012 name-mangling
add a comment |
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.
c++ visual-studio-2012 name-mangling
add a comment |
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.
c++ visual-studio-2012 name-mangling
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.
c++ visual-studio-2012 name-mangling
c++ visual-studio-2012 name-mangling
edited Sep 8 '15 at 3:41
Bill Lynch
59.8k1196142
59.8k1196142
asked Sep 8 '15 at 1:29
BenevolentDeityBenevolentDeity
17410
17410
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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.
Did anyone file a bugreport about this?
– MikeMB
Sep 8 '15 at 2:56
@MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).
– James McNellis
Sep 8 '15 at 12:13
@James McNellis I do have an additional question about your statement thatchar*
is equivalent tochar** const
in my example. Whyconst
? I've always thought that for parameters only,*
is equivalent to**
, but it seems I may be mistaken. Is const somehow implied by? The C99 language says that both
argv
and the strings it represents shall be modifiable (although it says nothing about the actual elements ofargv
). I couldn't find this statement in C++11, however.
– BenevolentDeity
Sep 8 '15 at 19:44
add a comment |
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.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f32447978%2fodd-vs-name-mangling-behavior%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
Did anyone file a bugreport about this?
– MikeMB
Sep 8 '15 at 2:56
@MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).
– James McNellis
Sep 8 '15 at 12:13
@James McNellis I do have an additional question about your statement thatchar*
is equivalent tochar** const
in my example. Whyconst
? I've always thought that for parameters only,*
is equivalent to**
, but it seems I may be mistaken. Is const somehow implied by? The C99 language says that both
argv
and the strings it represents shall be modifiable (although it says nothing about the actual elements ofargv
). I couldn't find this statement in C++11, however.
– BenevolentDeity
Sep 8 '15 at 19:44
add a comment |
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.
Did anyone file a bugreport about this?
– MikeMB
Sep 8 '15 at 2:56
@MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).
– James McNellis
Sep 8 '15 at 12:13
@James McNellis I do have an additional question about your statement thatchar*
is equivalent tochar** const
in my example. Whyconst
? I've always thought that for parameters only,*
is equivalent to**
, but it seems I may be mistaken. Is const somehow implied by? The C99 language says that both
argv
and the strings it represents shall be modifiable (although it says nothing about the actual elements ofargv
). I couldn't find this statement in C++11, however.
– BenevolentDeity
Sep 8 '15 at 19:44
add a comment |
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.
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.
answered Sep 8 '15 at 2:50
James McNellisJames McNellis
286k59803906
286k59803906
Did anyone file a bugreport about this?
– MikeMB
Sep 8 '15 at 2:56
@MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).
– James McNellis
Sep 8 '15 at 12:13
@James McNellis I do have an additional question about your statement thatchar*
is equivalent tochar** const
in my example. Whyconst
? I've always thought that for parameters only,*
is equivalent to**
, but it seems I may be mistaken. Is const somehow implied by? The C99 language says that both
argv
and the strings it represents shall be modifiable (although it says nothing about the actual elements ofargv
). I couldn't find this statement in C++11, however.
– BenevolentDeity
Sep 8 '15 at 19:44
add a comment |
Did anyone file a bugreport about this?
– MikeMB
Sep 8 '15 at 2:56
@MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).
– James McNellis
Sep 8 '15 at 12:13
@James McNellis I do have an additional question about your statement thatchar*
is equivalent tochar** const
in my example. Whyconst
? I've always thought that for parameters only,*
is equivalent to**
, but it seems I may be mistaken. Is const somehow implied by? The C99 language says that both
argv
and the strings it represents shall be modifiable (although it says nothing about the actual elements ofargv
). I couldn't find this statement in C++11, however.
– BenevolentDeity
Sep 8 '15 at 19:44
Did anyone file a bugreport about this?
– MikeMB
Sep 8 '15 at 2:56
Did anyone file a bugreport about this?
– MikeMB
Sep 8 '15 at 2:56
@MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).
– James McNellis
Sep 8 '15 at 12:13
@MikeMB I am sure that numerous bugs have been reported about this over the years. You are welcome to open another one at connect.microsoft.com/VisualStudio, if you'd like. Note that this is the sort of bug where the cost of fixing it is very high but the benefit of the fix is very low. It's not likely that this will be fixed any time soon (if ever).
– James McNellis
Sep 8 '15 at 12:13
@James McNellis I do have an additional question about your statement that
char*
is equivalent to char** const
in my example. Why const
? I've always thought that for parameters only, *
is equivalent to **
, but it seems I may be mistaken. Is const somehow implied by
? The C99 language says that both argv
and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv
). I couldn't find this statement in C++11, however.– BenevolentDeity
Sep 8 '15 at 19:44
@James McNellis I do have an additional question about your statement that
char*
is equivalent to char** const
in my example. Why const
? I've always thought that for parameters only, *
is equivalent to **
, but it seems I may be mistaken. Is const somehow implied by
? The C99 language says that both argv
and the strings it represents shall be modifiable (although it says nothing about the actual elements of argv
). I couldn't find this statement in C++11, however.– BenevolentDeity
Sep 8 '15 at 19:44
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited Sep 8 '15 at 2:25
answered Sep 8 '15 at 2:12
rcgldrrcgldr
15.2k31333
15.2k31333
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f32447978%2fodd-vs-name-mangling-behavior%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown