Martijn Courteaux
Martijn Courteaux

Reputation: 68847

Is this code valid, or is it the compiler?

int cpu = 0;
int player = 0;

char * getPoints()
{
    using namespace std;
    string str = "You: ";
    str += player;
    str += " CPU: ";
    str += cpu;
    char c [100];
    strcpy(c, str.c_str());
    return c;
}

This code doesn't compile. Is the code wrong or is there something wrong with my compiler?

I'm using Microsoft Visual Studio with the DarkGDK.

If it is me, can someone improve it?


This is the output:

1>------ Build started: Project: Pong, Configuration: Debug Win32 ------
1>Compiling...
1>Main.cpp
1>c:\users\martijn\documents\visual studio 2008\projects\pong\pong\main.cpp(42) : warning C4172: returning address of local variable or temporary
1>Linking...
1>libcpmtd.lib(xdebug.obj) : warning LNK4098: defaultlib 'libcmt.lib' conflicts with use of other libs; use /NODEFAULTLIB:library
1>libcpmtd.lib(xdebug.obj) : error LNK2019: unresolved external symbol __malloc_dbg referenced in function "void * __cdecl operator new(unsigned int,struct std::_DebugHeapTag_t const &,char *,int)" (??2@YAPAXIABU_DebugHeapTag_t@std@@PADH@Z)
1>libcpmtd.lib(xdebug.obj) : error LNK2019: unresolved external symbol __free_dbg referenced in function "void __cdecl operator delete(void *,struct std::_DebugHeapTag_t const &,char *,int)" (??3@YAXPAXABU_DebugHeapTag_t@std@@PADH@Z)
1>libcpmtd.lib(stdthrow.obj) : error LNK2019: unresolved external symbol __CrtDbgReportW referenced in function "void __cdecl std::_Debug_message(wchar_t const *,wchar_t const *,unsigned int)" (?_Debug_message@std@@YAXPB_W0I@Z)
1>Debug\Pong.exe : fatal error LNK1120: 3 unresolved externals
1>Build log was saved at "file://c:\Users\Martijn\Documents\Visual Studio 2008\Projects\Pong\Pong\Debug\BuildLog.htm"
1>Pong - 4 error(s), 2 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Upvotes: 1

Views: 5768

Answers (4)

Matteo Italia
Matteo Italia

Reputation: 126777

The concatenation you're doing doesn't do what you think; the += operator of std::string accepts only std::string, char * or char, so the ints you're trying to append get converted to chars, so each of them is being considered a single ASCII character to be appended to the string. If you want to build strings from many variables of different types, you should consider using the string streams (sstream header) or the boost casts.

Moreover, you're returning a pointer to a local object, that is going to disappear when the function will return, so the caller will have a pointer to garbage; it may appear to work if it's used just after the function returned, because that portion of stack may not have been overwritten yet, but you're in the land of undefined behavior, and it will fail hard if you'll try to use that pointer after another function call.

You need to return a std::string, so the caller will get its own copy of the string. Then, if it will need a C string (ASCIIZ), it'll be able to get it from the std::string calling the c_str() method.

The errors you posted are related to the linker; that kind of errors usually come up when you are linking against a static library compiled with a different version of the CRT; to solve the problem, recompile your project and the library with the same version of the CRT.

Upvotes: 4

Mike
Mike

Reputation: 61

The LNK4098 error indicates your build is mixing code that was compiled with DEBUG settings (thus using libcmtd.lib) and code that was compiled with non-DEBUG settings (thus using libcmt.lib).

OR: It could be code using the static runtime libs (libcmt.lib) mixed with code using the dynamic runtime libs (msvcrt.lib).

The linker then finds two different versions of common runtime library methods/classes and can't figure which to use. You can't mix multiple runtime libs in one build.

In either case, it's a solution/project setup problem. We ran into that when we were trying to link with libs/dlls provided by other people where they built them with different settings than we used.

The /NODEFAULTLIB argument (available under VS Linker options as "Ignore Libraries" or similar) allows you to force one or more of those runtime library sets to be ignored, leaving only one runtime library set to use.

Upvotes: 6

Bruno Brant
Bruno Brant

Reputation: 8554

Martjin,

Your code have some bugs which will make the program crash, once run. But still, none of them should stop you from compiling/linking it. As dirkgently stated, you problem is with the linker and not with the compiler, meaning that your code correctly generates a object, but when VS tries to create an executable, it doesn't find the necessary simbols.

You should look at your SDK documentation in order to learn how to correctly link your objects with its libraries. Once that is done, all the undefined externals should be resolved, which would enable you to create your executable.

Upvotes: 2

Hans W
Hans W

Reputation: 3891

The errors seem to be from problems with the compiler. Are you sure you have the project set up correctly?

The warning about returning a local variable is serious. You allocate the c array on the stack in your function. When the function returns, the array will be gone from the stack and the pointer you returned ends up pointing to garbage. Consider returning a string instead, or allocate c on the heap.

Upvotes: 4

Related Questions