Skip to main content
GameDev.net gamedev.net
🔒 Locked

Strange Linker Error

Started by Mr Awesome Jan 8, 2007 at 9:11 PM 8 replies 1k views
Original Post
Mr Awesome
Mr Awesome
When I try to build the following code from a fresh Microsoft Visual Studio 2005 Express Edition project, I get the following linker error:
// Code:
#include <iostream> 
#include <fstream> 
#include <string> 

int main() 
{ 
    std::ifstream fin("foo"); 
    std::string str(std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>()); 
    std::cout << str; 
}

// Linker error:
unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl script(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_traits<char> > (__cdecl*)(void))"
Another person has confirmed the same error. Does anyone else get this when building the above code? If you can get this code to compile and link with VC++ 8, please post what project options you are using. Thanks in advance. [Edited by - Mr Awesome on January 8, 2007 10:46:55 PM]
Enigma
Enigma
Welcome to C++'s most vexing parse.

The fix:
#include <iostream> #include <fstream> #include <string> // for istreambuf_iterator, you may get away without it but it's bad practice#include <iterator>int main() {     std::ifstream fin("foo");     std::string str(<font color="red">(</font>std::istreambuf_iterator<char>(fin)<font color="red">)</font>, std::istreambuf_iterator<char>());     std::cout << str; }
The explanation:
C++ will parse anything it can as a function declaration. The line with the fix was originally parsed as a declaration of a function returning a std::string taking as parameters a std::istreambuf_iterator< char > with name fin and a pointer to a function taking no parameters and returning a std::istreambuf_iterator< char >. The address of this function is then taken in the last line and printed to std::cout, causing a linking error since the function is never defined.

The additional parenthesis make it an illegal function declaration, thus forcing the line to be parsed as a local variable definition. An alternative fix is to use named temporaries for your parameters.

Σnigma
Mr Awesome
Mr Awesome
Thanks a lot Enigma, it links just fine now. That seems very strange that it would consider that a function declaration, considering you can't have those within functions. What is also strange is that this code compiled and linked using gcc.
Brother Bob
Brother Bob
Quote:
Original post by Mr Awesome
Thanks a lot Enigma, it links just fine now. That seems very strange that it would consider that a function declaration, considering you can't have those within functions. What is also strange is that this code compiled and linked using gcc.

Declaring a function prototype inside a function is perfectly legal.
JasonBlochowiak
JasonBlochowiak
Quote:
Original post by Brother Bob
Quote:
Original post by Mr Awesome
Thanks a lot Enigma, it links just fine now. That seems very strange that it would consider that a function declaration, considering you can't have those within functions. What is also strange is that this code compiled and linked using gcc.

Declaring a function prototype inside a function is perfectly legal.


Not if it's a template function, at least under .NET 2003's implementation of C++. Can't quote the standard off the top of my head on this one, though. :)
Crypter
Crypter
Quote:

Declaring a function prototype inside a function is perfectly legal.

Im curious as to why this is legal.. How would one define such a function?
Brother Bob
Brother Bob
Quote:
Original post by Crypter
Quote:

Declaring a function prototype inside a function is perfectly legal.

Im curious as to why this is legal.. How would one define such a function?

Why it is legal? For the (partly) same reason you can declare variables in a limited scope I guess; to not pollute an unecessary large name space scope. And you do it just like you do it at file scope. Just move the declaration to the point where you first need the name.

Say you have a large file, and a certain function is only needed within a tiny for-loop deeply nested into a function. Why force the programmer to declare the name at file scope, polluting the file scope name space with a symbol name that is not needed in most of the file.

main.cpp
#include <iostream>using namespace std;int main(int, char **){	for(int i = 0; i < 10; ++i)	{		// declare foo in a limited name space scope		int foo(int);		cout << foo(i) << endl;	}}

foo.cpp
int foo(int bar){	return bar * 2;}

Now I have to admit that I rarely, very rarely, declares functions other than at file scope name space myself. But it's possible, and there's no reason not to allow it... that I know of.
Crypter
Crypter
Thank you for the explination.. I asked because I have never used (nor seen) functions declared locally within another routine.

Dont know of any usefull use for it though. Nontheless, its good to know for that one day I might find it useful [smile]

Thanks again!
Mr Awesome
Mr Awesome
I don't believe there's anything for which this method is the only available option, but it can be useful if you use a lot of small functions for std algorithms that you don't want polluting the global namespace. Since std algorithms require separate functions, this method could make it more convenient I suppose. Good to know. :)
JasonBlochowiak
JasonBlochowiak
Quote:
Original post by Crypter
Thank you for the explination.. I asked because I have never used (nor seen) functions declared locally within another routine.

Dont know of any usefull use for it though. Nontheless, its good to know for that one day I might find it useful [smile]


Yep, this is generally something that's good to avoid. In fact, it's good to avoid function declarations in .cpp files in general - they should all be in header files. Why? Well, if the function signature changes, having to chase down all the .cpp files with the prototype in them can be tedious and error prone - and if you miss one, very bad things can happen, as any module that has a mismatching signature will call the function incorrectly.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.