I am working on a C++ project that uses Qt (gui lib), VTK (graphics lib) and another library which is so obscure I won't mention its name and will instead call it LIB_X. The project uses Qt for the gui components and VTK (more precisely the QVTKWidget extension provided by VTK that supports Qt) for rendering geometry.. and it uses LIB_X to gather and manipulate geometry.
The problem is that it turns out that LIB_X actually uses VTK (where and how, I don't know, it's closed source). At first there was no problem, compiling with both libs linked was going fine, but at some point I called a certain (and highly needed) LIB_X function and compiling led to a bunch of 'blah blah something about a VTK lib/obj already defined in LIB_X dll' errors.
e.g. (and note this is with /FORCE:MULTIPLE so it's a warning here, let me know if you want the error without /FORCE:MULTIPLE and I'll post it):
1>LIB_X.lib(LIB_X.dll) : warning LNK4006: "public: __thiscall std::vector<double,class std::allocator<double> >::~vector<double,class std::allocator<double> >(void)" (??1?$vector#NV?$allocator#N#std###std##QAE#XZ) already defined in vtkCommon.lib(vtkInformationDoubleVectorKey.obj);
I tried using /FORCE:MULTIPLE and it seemed to be a miracle at first, but I am getting random errors in code that would mostly give heap errors. I decided to remove all references to LIB_X from the main project and created a static lib that would handle all LIB_X stuff. I'm not a C++ expert, so I'm not certain how it handles lib clashing when you're using a pre-compiled lib, but I still received lib clashing errors when linking my static lib into my main project, so I still have to use /FORCE:MULTIPLE.
Once I had the static lib it seemed like the random errors had gone away, I was able to do a lot with LIB_X methods in the main project via the static lib, BUT out of nowhere, I added a new data member to my main project's class (a std::vector of doubles) and suddenly I was getting a heap error in one of my static library's methods. If I commented out the new data member, the static library's method would run fine. I hate to give the current error, because honestly I'm not sure if examining it will be worthwhile, but here it is anyway in case it can help:
note: it crashes to xutility on about line 151, pops up assertion:
"file: dbgheap.c line: 1279 expression: _CrtIsValidHeapPointer(pUserData)"
The error comes after adding a vector vector double to a vector vector vector double, crashing on the push_back line:
std::vector<std::vector<double>> tmpVec;
for(srvl_iter = srvl.begin(); srvl_iter != srvl.end(); ++srvl_iter)
{
tmpVec.push_back((*srvl_iter).getControlPoints());
}
this->_splines.push_back(tmpVec); //CRASH
It only started crashing here when I added a new data member to my main project (separate from the static lib!) Commenting out the new data member takes the error away.
std::vector<std::vector<std::vector<double>>> _geometry;
So, /FORCE:MULTIPLE seems bad, I get random errors that just don't make sense to me. Are there other solutions? Am I screwed? Is there something I can do with LIB_X's linking of VTK?
I encountered a bunch of LNK4006 errors when linking my app to a library (call it library LIB_Y) that made heavy use of std::vector<std::string>, which I also did in my app. After a bit of experimenting I found one solution that worked -- wrap LIB_Y in a separate DLL that calls LIB_Y (LIB_Y_WRAPPER, say), and then link the main app against LIB_Y_WRAPPER.
To try out my suggestion you will need to:
Change your "static lib that handles all LIB_X stuff" from a static LIB project into a DLL project (which I will call LIB_X_WRAPPER).
Make sure the header files of LIB_X_WRAPPER don't include any of the LIB_X header files. This is really important because the wrapper needs to completely isolate your app from the data types declared in the LIB_X header files (such as std::vector<double>). Only refer to LIB_X's header files from within the source files of LIB_X_WRAPPER.
Change the declaration of all classes and functions in your static lib to ensure they are exported from the DLL (see this answer if you need details about exporting from a DLL).
This solution worked for me because it kept the instantiation (compiler generated functions) of the std::vector<std::string> class used by LIBY completely separate from the instantiation of std::vector<std::string> in my app.
As an aside, I suspect the cause of the crash you are seeing (you comment it is in the destructor of std::vector<double>) is because the instantiation of std::vector<double> in your app is different to that in LIB_X.
The commenting out is probably just random luck - if you are corrupting the heap you don't always see it right away but an stl vector will allocate and deallocate things left and right so it's no wonder it's finding the error.
Some libs require you include things in a certain order. I am not sure why exactly because to me it seems like giving up and saying you can't design a library properly, but it's the sad fact. So long as you don't include this lib_x anywhere that you include vtk it should be fine, though.
However, they might be fighting over some resource or using something improperly that makes it impossible for them to work together. If you are able to get the compile to work ok by segregating them and it still fails then yes you are just out of luck because it's just a failing in the way that this lib_x was designed and since it's so obscure it's not likely to have been thoroughly debugged against all uses. When something's not widely used it usually ends up being something that works on the developer's machine and project but not necessarily anyone else's.
Related
I am trying to write a plugin for a popular program whose code and compilation process I do not have control over. The program is written in C. However, I have written parts of my plugin in C++, since I use the QT5 library for graphics capabilities. The functions that the C program calls are written in C.
When the C program tries to load the plugin (shared library), it produces this error:
dlopen('build/libfoo.so') failed: build/libfoo.so: undefined symbol: _ZTV13JoystickPanel
JoystickPanel is a class in the C++ part of the program.
I've tried rewriting parts of the program in C, but the error was unaffected. I know that I could rewrite the entire program in C, but I'd rather not have to switch to another, more C-friendly GUI framework. I've also opened up libfoo.so in a text editor and search for JoystickPanel, but it appears to be mangled as _ZN13JoystickPanel.
Are there any compiler options or solutions that I'm missing?
I have no idea what _ZN13JoystickPanel means, since it's not apparently a valid mangled C++ name. It should perhaps be _ZN13JoystickPanelE, which would translate to JoystickPanel. That'd be symbol name for sure, but without much meaning anyway. You must have truncated something: I tried quite a bit and just can't generate an object file that would include _ZN13JoystickPanel as the complete symbol. It's just a prefix, there should be a "second half" attached to it - was there?
But _ZTV13JoystickPanel is the vtable for the JoystickPanel class. It's missing because you didn't provide implementations for all the virtual methods of the JoystickPanel class. Most likely, you didn't invoke moc properly, or forgot to compile and link its output.
You need to show a complete build script for your plugin at the very least (the .pro file, or CMakeLists.txt). You'll also need to provide a github link to your project (I presume it's open source).
The symbols you want to find in the compiled output are at least _ZTV13JoystickPanelD#Ev - virtual destructors, where # is a digit, _ZTV13JoystickPanel - the virtual method table,
Those symbols may be absent when compiled with optimization and/or LTCG, but also absent will be references to them.
You may wish to delete the build folder and rebuild your project, just to be sure. qmake is bad at dependency generation for the makefiles it produces, so if you use it, I suggest switching to cmake + ninja.
Apparently, I'd forgetten to put the #include "moc_controller.cpp" line at the bottom of a file that needed it.
For anyone else chasing this issue while using Qt on CMake, consider making sure that the proper lines are added.
Situation:
Static library LIB1, compiled from source and linked as lib1.lib (with /MD).
Uses library LIB2 and has inside objects from lib2.lib
Static library LIB2, also compiled with /MD.
EXE that (not directly) depends on both libraries.
Result of linking this EXE on MSVC 15.9.19: a lot of LNK2005 errors like
lib2.lib: error LNK2005: "function <funcsig> already defined in lib1.lib"
Also I get a lot of warnings like
lib1.lib: warning LNK4099: PDB 'lib2.pdb' was not found with 'lib1.lib' or at '<path>'; linking object as if no debug info
The question: why didn't the linker merge duplicate definitions? How do I diagnose the exact reason for this problem?
Thanks!
UPDATE:
The errors are NOT about the standard library. They are about the Google Protobuf functions. LIB2 is Google's libprotobuf.lib. LIB1 is also Google's OR-Tools library that uses Protobuf. But we also use Protobuf, hence the conflict!
This link to MSDN will almost certainly help.
As you say these are not standard C/C++ functions, you can ignore the sections about the mixing Debug and Release code. Unfortunately this still leaves you with plenty of possible causes. This one is a good one to rule out.
This error can occur if you mix use of static and dynamic libraries when you use the /clr option.
If you view the command line options as you compile, either by switching on verbose mode or examining the properties of each file.
Once this is ruled out, all the other causes are that you literally declaring the same thing (function/variable) twice. The most likely way for this to happen is to put something (like a function) in a header file, which is included by more than one module file. Diagnosing this without seeing the code is hard. You must pick one of the errors, and select part of the name that is not mangled, basically the human readable bit. You then need to examine where it is declared, and see if is in a header. If it is not, you must be including a non-header from a source file. A quick (and dirty) way to find where a file is included from is to add a #pragma message to the file, then recompile one file at a time to see when it is printed. To understand why it is included use show includes.
If the symbol is declared from a header file, you must fix it, by making it a forward declare.
If you don't know how to do this, I would suggest starting a new question, along the lines of, "how do I forward declare this?". It should get you answers pretty quickly.
Hope this helps.
I'm working on a library that links another library to use its static functions.
Everything was working perfectly until I switched from including all my code in the header file to sharing it between the .h and .cpp file.
I tried to use ./configure --prefix="<same path as before>" and then make install but ended up with a "/usr/bin/install: cannot stat .libs/<library name>.so.0.0.0': No such file or directory" error. (also, I did change my makefile to accommodate for the inclusion of the .cpp file)
Then, trying to compile my old library (which should've still worked since the linked library didn't make install correctly and was still technically using the older version) I get a pile of errors that seem to have to do with c++ itself. For example:
.../gcc/4.9.1/linux64/include/c++/4.9.1/bits/stl_bvector.h:354:13: error: expected ';' at end of member declaration
There are an absolute ton of errors similar to the one above, all having to do with issues in the path .../gcc/4.9.1/linux64/include/c++/4.9.1/
Has anyone run into this error before? Let me know if I need to provide any more information, it's just that I've never had this happen so I'm at a loss as to where to proceed. It's likely something simple I'm missing but the longer I stare at it the less it makes sense.
Thanks!
Update: I ended up solving the issue I was having. Basically, the .so file was not being accessed, so I used make clean and then the linked library compiled properly. Next, the issues with the base library was just an extra character within a header file that was causing the compiler to blow up with over 1500 lines of errors. After fixing that, it was able to link up properly and is working fine now.
I'm not too sure of how to ask this, so please comment if I'm being unclear about something.
I have a project which uses a custom class called CManager. Most of my classes in this project inherit from this one and in CManager() (constructor), I add one to the count of CManager object, the count being a static variable in this class. Now, this project used to be compiled as a .dll (dynamic library), but my employer asked me to compile it as a .lib this time, while stripping away a lot of code. Now I have stripped away all the code that wasn't needed and compile it without error... But, when I am creating a .lib, I get an error when I try to execute the program saying that there is an unhandled access violation reading. Here is the code
int CManager::m_count = 0;
CManager::CManager()
{
++m_count; <- Exception here
}
I don't know why I have this error. m_count is a private static int variable declared in the .h.
Since I didn't understand why it wasn't working, I tried compiling the project as a .dll, just so I wouldn'd be doing nothing. And for some reason... it worked. It compiles AND execute (run, wtv).
Now my question is... why is this happening? What explains this?
PS: This project has to include 5 other projects' .lib (or dll), but it work either ways. This project is included by my main, and it is when I try to execute my main that I get the error. The project is just a bunch of algorithms, my main app being the GUI. My main app is an MFC app.
Thanks!
EDIT 1:
While debugging, I found out that if I import the project using a static lib, when passing from my main's function call to the .lib implementation, I loose the object: I call a function on my object, and when I'm in the function, the value of this (refering the object) is null.
If I used a dll, it works perfectly. The object keep its value when a function is called on it.
But I still want to use a .lib, so I don't really know why this happens and how to fix it.
I found it. Like Mark Ransom said in the comments, the problem was not in the code, it was in my project properties. I was creating a .lib instead of dll, but didn't change the runtime library accordingly. So in Project Properties -> C/C++ -> All Options -> Runtime Library, I started using MD and it worked.
Also make sure Runtime Library and general use of MFC are compatible, look here for details.
I'm still not to sure of how using MT created problems, but at least I can run my program now.
I am making a static library of my own. I have taken my code which works and now put it into a static library for another program to use. In my library I am using another static library which I don't want the people who will be using my API to know. Since, I want to hide that information from them I can't tell them to install the other static library.
Anyway, I used the command line Lib.exe to extract and create a smaller lib file of just the obj's I used. However, I get a bunch of LNK4006 :second definition ignored linker warnings for each obj I use followed by LNK4221 no public symbols found;archive member will be inaccessible.
I am doing this work in vs2008 and I am not sure what I am doing wrong.
I am using the #pragma comment line in my .cpp file
I have also modified the librarian to add my smaller .lib along with its location.
my code simply makes calls to a couple functions which it should be able to get from those Obj file in the smaller lib.
All my functions are implemented in .cpp file and my header just have the includes of the third party header files and come standard c++ header files. nothing fancy. I have actually no function definitions in there atm. I was going to put the API definition in there and implement that in the .cpp for this static lib that i was going to make. However, I just wanted to build my code before I added more to it.
I did read http://support.microsoft.com/default.aspx?scid=kb;EN-US;815773 but it did not provide a solution.
Even if you extract all objects from the other library and put them in your own library, your users will still be able to see what's in your library and thus see all the object names. In many cases the names of the objects will reveal what's actually the other library you are using.
Instead of distributing your library as a static library, consider distributing it as a DLL. In the DLL you can easily hide all the underlying things and only make public what you want to make public.