I have the below code that links and runs fine in 32bit mode -
#include "safeint3.hpp"
typedef SafeInt<SIZE_T> SAFE_SIZE_T;
SAFE_SIZE_T sizeOfCache;
SAFE_SIZE_T _allocateAmt;
Where safeint3.hpp is current version that can be found on Codeplex SafeInt. For those who are unaware of it, safeint is a template class that makes working with different integer types and sizes "safe". To quote channel 9 video on software - "it writes the code that you should".
Which is my case. I have a class that is managing a large in-memory cache of objects (>6gb) and I am very concerned about making sure that I don't have overflow/underflow issues on my pointers/sizes/other integer variables. In this use, it solves many problems.
My problem is coming when moving from 32bit dev mode to 64bit production mode. When I build the app in this mode, I'm getting the following linker warnings -
1>cachecontrol.obj : warning LNK4006: "bool __cdecl IntrinsicMultiplyUint64(unsigned __int64 const &,unsigned __int64 const &,unsigned __int64 *)" (?IntrinsicMultiplyUint64##YA_NAEB_K0PEA_K#Z) already defined in ImageInRamCache.obj; second definition ignored
1>cachecontrol.obj : warning LNK4006: "bool __cdecl IntrinsicMultiplyInt64(__int64 const &,__int64 const &,__int64 *)" (?IntrinsicMultiplyInt64##YA_NAEB_J0PEA_J#Z) already defined in ImageInRamCache.obj; second definition ignored
While I understand I can ignore the error, I would like either (a) prevent the warning from occurring or (b) make it disappear so that my QA department doesn't flag it as a problem. And after spending some time researching it, I cannot find a way to do either.
The problem is that inside safeint3.hpp, the code looks like this:
bool IntrinsicMultiplyUint64( const unsigned __int64& a, const unsigned __int64& b, unsigned __int64* pRet )
{
....
}
This means every translation unit that includes safeint3.hpp will get a definition of IntrinsicMultiplyUint64. If you are willing to modify that file, you can make those functions inline:
inline bool IntrinsicMultiplyUint64( const unsigned __int64& a, const unsigned __int64& b, unsigned __int64* pRet )
{
....
}
Are these function declared and defined in the header file and not declared as inline by any chance?
It looks like they're quasi-inlined but the symbols are visible outside the object file, which they shouldn't be.
If that's the case, simply declaring them as inline should fix the issue.
Regarding your question about disabling the warning, this should do it:
#pragma warning(disable:4006)
Related
I am willing to make a 2D game with SDL and I am following a Shaun Mitchell's book. But I faced serious difficulties with this user-defined type conversion error when trying to compile my project...
Also, I am unfamiliar with this topic. I've watched some tutorials and searched the web for a solution.
Do I need to add
operator std::string&() const { return ???;}
to the tinyxmlstr.h in TiXmlString class? If so, how to implement it? What should I return?
The Errors
If I don't define the STL (which I use) in tinyxml.h, the compiler then returns a linkage error.
Error 19 error LNK2019: unresolved external symbol "public: virtual __cdecl TiXmlNode::~TiXmlNode(void)" (??1TiXmlNode##UEAA#XZ) referenced in function "public: virtual __cdecl TiXmlDocument::~TiXmlDocument(void)" (??1TiXmlDocument##UEAA#XZ)
Without STL
StateParser class and implementation is the same as the one in the book.
Finally, if I have a mistake somewhere, how to debug it properly and where to look for it? Thank you, in advance!
The error is clear: non conversion available from const TiXmlString to const std::string &.
According to this page, if I'm not wrong, there isn't even a direct conversion from TiXmlString to a std::string
I suppose you can write a method like this (exactly like the value() that return a const char *)
std::string valueStr () cont
{ return value.c_str(); }
but in this way you return a copy of value (so return a const std::string, instead a plain std::string, is useless), not a reference. I don't know if this it's OK for you.
I'm getting this error from the linker:
1>PACBalancesTest.obj : error LNK2001: unresolved external symbol "public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const " (??RBalChgKeyComparator#PAC##QBE_NABVBalChgKey#1#0#Z)
I must be missing something really obvious, because I've looked at the definition of the "missing" symbol repeatedly and can't see any problem.
The symbol's definition is in a .lib file. I see the following in the output from dumpbin /symbols on that .lib file:
2F0 00000000 SECTFD notype () External | ??RBalChgKeyComparator#PAC##QBE_NABVBalChgKey#1#0#Z (public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const )
And there are other symbols being resolved successfully from that .lib file! (In fact, from the same .obj.) [Update: I no longer think the preceding statement is true. This may be my first attempt to access any function not defined in a .h file.]
WHAT FOLLOWS IS NOT RELEVANT TO THE PROBLEM -- SO PLEASE DON'T SPEND TIME STUDYING IT!
Here's the declaration of the function (in PACBalances.h):
namespace PAC {
class BalChgKey {
public:
...
};
struct BalChgKeyComparator {
bool operator()(const BalChgKey& lhs, const BalChgKey& rhs) const;
};
typedef std::multimap<BalChgKey, long, BalChgKeyComparator> BalChgKeyLongMMap;
};
Note that I've tried changing 'struct' above to 'class', with no effect.
Here is the calling code (in a cpputest test file):
#include "CppUTest/TestHarness.h"
#include <utility>
#include <map>
#include "PACBalances.h"
using namespace PAC;
...
TEST_GROUP(PACBalanceCUMap)
{
BalChgKeyLongMMap empty;
BalChgKeyLongMMap onesy;
void setup()
{
// **Adding the following line caused this error to start to occur.**
onesy.insert(std::pair<BalChgKey, long>(BalChgKey(BOPCAT_FEE, PAYMTYPE_OVERDRAFT_FEE, 4321, 41100, 1, 17), 17));
}
void breakdown()
{
}
};
And here is the definition of the operator function itself:
bool PAC::BalChgKeyComparator::operator()(
const BalChgKey& thing1,
const BalChgKey& thing2
) const
{
if (thing1.m_balKey.m_balCat < thing2.m_balKey.m_balCat) return true;
else if (thing1.m_balKey.m_balCat > thing2.m_balKey.m_balCat) return false;
// Fall thru if balCats are equal
...
return false;
}
Please note that:
The comparator, and the typedef'd multimap, works beautifully in lots of code (not shown above).
The test file calls lots of other functions declared and defined in that .h file, but this is the first time I've tried calling a function defined in a separate .cpp file.
My question is not why does the 'onesy.insert' call requires the comparator function. I understand that. It just happens to be the first multimap operation that I've coded in the test set that actually uses the comparator.
I have various hunches, but I'm running out of them, so if someone who knows about this stuff can give me any leads I would be very grateful.
Norm
#panta rei: You provided the key in your comment. (Sorry, can't figure out how to type Greek letters here.)
The problem was basically that I didn't know how to tell Visual Studio what objects to link in. I had told my solution that AnalyticsUTest depended on AnalysticsUTested, but the linking step is performed by the project (AnalyticsUTest), not the solution, so I needed to tell the project to include this .lib file.
So I went to the project's properties sheet and created two new macros, one giving the folder where VS was putting my .lib file (ANALYTICSUTESTED_LIB_PATHS), the other giving the name of my .lib file (ANALYTICSUTESTED_LIB_DEPENDENCIES) -- both by analogy with the CPPUTEST_LIB* macros.
And then I added $(ANALYTICSUTESTED_LIB_PATHS) to Linker > General > Additional Library Directories. And I added $(ANALYTICSUTESTED_LIB_DEPENDENCIES) to Linker > Input > Additional Dependencies.
And that fixed my problem! (I've spelled it out here in case another newbie like me comes along and needs it.)
Thank you, panta rei. How do I give you points for an answer provided via a comment?
I have a Visual Studio 2012 project equivalent to this:
Header.h
template< class T >
inline int Demonstrate( const char *txt, T *input )
{
return printf("%s %d %f\n", txt, input->Integer(), input->Real() );
}
Source.cpp
#include "Header.h"
class Foo
{
public:
int Integer() { return 2; }
float Real() { return 3.14159f; }
};
int main()
{
Foo example;
printf( "%d\n", Demonstrate( "foo:", &example ) );
return 0;
}
Yet when I compile I receive a LNK2019 error:
unresolved external symbol "int __cdecl Demonstrate(char const *,class Foo *)"
Ordinarily this occurs when a templated function is declared in a header but only defined in a cpp, but that is not the case here. The function is defined inline in the header.
What could cause this and how can I fix it?
edit
This happens even if I remove the header altogether and just stick Demonstrate() at the top of Source.cpp. It happens whether "Inline Function Expansion" in the project properties is set to "Default" or to "/Ob2" . This must be some project settings thing, but what?
So I tracked this down and it turns out that Joel was on the right path. The function Demonstrate() had been prototyped multiple times in multiple headers — in a very nonobvious way. There was the explicit int Demonstrate( const char *txt, Foo *input ) declaration, which is what I replaced with a template.
But there were several other headers that had, strewn across them, something analogous to this (you can infer that the actual function and class names were much more complicated):
header a.h:
#define FUNC_PREFIX Demo
header b.h:
#define REGISTER_CLASS( retype, classname, FUNC_SUFFIX ) retype FUNC_PREFIX ## FUNC_SUFFIX ( const char *txt, classname *ptr )
header c.h:
REGISTER_CLASS( int, Foo, nstrate );
REGISTER_CLASS( int, Bar, nstrate );
// etc
I'm not sure what to draw from this. On the one hand it's a very specific bug to a very specific codebase and too localized to be a useful SO question. On the other hand, there is a teachable moment here:
DON'T USE MACROS TO DEFINE GLOBAL FUNCTIONS IN SNEAKY WAYS.
Or else poor saps like me will spend hours tracking down problems like this.
Sometimes you can't rely on automatic template specialization. I've encountered this before with VS and ended up having to be explicit. ie
Demonstrate<Foo>("foo:", &example)
Ok a little introduction into the issue: I'm working on a rendering engine(compiling in 32 bit mode) in C++/DirectX11 in Visual Studio 2012 running on Windows 7 - 64 bit OS and I have a strange link error that comes up in my Entity class (the Entity3D is like the basic actor of the scene).
All of my bounding volume classes inherit from a Shape3D class.Each Entity has a Shape3D* boundingVolume member in it, that is initialized to a specific shape type at initialization time.
When colliding between two Shape3D's I pass them trough a function - bool Intersect(Shape3D* a, Shape3D* b) the function then checks their types(Sphere/*Box*/Whatever) and the type represents a number which is the index of a function in an array of function pointers:
bool(*IntersectArray[4][4])(Shape3D* a, Shape3D* b) =
{
{
IntersectSphereSphere,
IntersectSphereBox,
IntersectSphereOrientedBox,
IntersectSphereFrustum,
},
{
IntersectBoxSphere,
IntersectBoxBox,
IntersectBoxOrientedBox,
IntersectBoxFrustum
},
{
IntersectOrientedBoxSphere,
IntersectOrientedBoxBox,
IntersectOrientedBoxOrientedBox,
IntersectOrientedBoxFrustum
},
{
IntersectFrustumSphere,
IntersectFrustumBox,
IntersectFrustumOrientedBox,
IntersectFrustumFrustum
}
};
So it's like a virtual dispatch. Ok so the InersectArray is the array of the functions(declared in Intersect.h) and that's what gives me the link error:
error LNK1169: one or more multiply defined symbols found
error LNK2005: "char (__cdecl*(* Engine::Collision::IntersectArray)[4])(class Engine::Collision::Shape3D *,class Engine::Collision::Shape3D *)" (?IntersectArray#Collision#Engine##3PAY03P6ADPAVShape3D#12#0#ZA) already defined in Entity3D.obj
File Intersect.obj
Intersect.h is only included in Entity3D.cpp, it's no included in Entity3D.h, nor in any of the headers that Entity3D.h includes.Entity3D.cpp only includes Entity3D.h and Intersect.h.I cleaned and rebuilt, error persists.Intersect(Shape3D a, Shape3D* b)* is called only in one method of Entity3D in the Entity3D.cpp file. There are no other compile errors or warnings currently in the project. What else could cause such an issue?
Fixed the issue, I just moved the definition of IntersectArray in the Intersect.cpp file, since for now that's the only place it's needed.
I am trying to link a DLL but I am constantly running into issues with UINT32.
The library is compiled against the 4.1 version of the Visual Studio compiler. The interface for my component (which was 4.1 and I am now porting to 2012) is defined with many UINT32s in it. In VC4.1 UINT32 is not defined by the compiler and so it was typedefed to unsigned long by the programmer, but from VC6 onwards UINT32 is defined as unsigned int. This makes my life hard.
My initial reaction was to try replacing all UINT32 in the interface with unsigned long and recompiling. This works as the function signatures are the same. However an unsigned long in 2012 is 64 bits wide... not 32 bits. This is not a problem in most cases but I foresee possible problems with flag parameters and return types.
What I am wondering is if I have missed a more obvious solution for this. I thought of defining a different type
typedef OAM_UINT32 unsigned long //in the library
typedef OAM_UINT32 unsigned int // in my component
But then the problem is going to be the same as what I have already with my two definitions of UINT32... right?
Any help would be much appreciated.
The Problem
Client code
#include <oam_if.h>
....
UINT32 uuid = getSomeLocalUserId();
UINT32 dwOamRetVal = dwOamGetUserDetails( uuid ); // LINK ERROR: Symbol not found
oam_if.h
UINT32 dwOamGetUserDetails( UINT32 idOfUser );
When the library (OAM) is compiled the UINT32 value is evaluated as an unsigned long. When the client component is compiled, UINT32 is evaluated as unsigned int. The linker complains because it has a symbol defined in the OAM library for dwOamGetuserDetails which rakes and returns an unsigned long, but the client is calling a function which according to it should take an unsigned int.
So while their respective inputs are unsigned numbers both 32 bits long, the signature of the function is different and the linker complains.
The only way I can see to fix it is to define everything as unsigned long directly. However then OAM will be using a 32 bit long number but the client will be using a 64 bit number!
Sample of Linker Error
error LNK2001: unresolved external symbol "public: virtual unsigned long __thiscall Message::getCallId(void)const " (?getCallId#Message##UBEKXZ) oam.lib(OAM_SsRequest.obj)
This is actually a callback from the library to the component, so in this case it is looking for a signature that matches UINT32 as defined by the libary (unsigned long) but the component is defining an unsigned int for its callback.