2015-07-27 8:54 GMT+02:00 Edward Diener <[email protected]>:
> On 7/24/2015 11:13 AM, Ruben Van Boxem wrote: > > 2015-07-24 17:03 GMT+02:00 Edward Diener <[email protected] > > <mailto:[email protected]>>: > > > > On 7/24/2015 8:54 AM, Riot wrote: > > > Where are you defining your template, in the header or the source? > You > > > may need to explicitly instantiate. > > > > The template is being defined in the YY.cpp source file. > > > > > > Could you send example files displaying the issue? It makes it easier to > > reproduce and debug the issue. > > Here are the files and the command lines. All files should be placed in > the same source directory with a 'debug' sub-directory where everything > will be built. You need to have the mingw-64 gcc-5.1 32-bit bin > directory in your PATH and you need to be in the source directory when > executing the commands. I am only concerned with problems linking and > not with running the result. > > First the header and source file to be built into a shared library: > > Header file exception_cl.hpp > > #ifndef EXCEPTION_CL_HPP > #define EXCEPTION_CL_HPP > > #include <exception> > > #if defined(BUILD_SL) > #define CLASS_DECL __attribute__((__dllexport__)) > #else > #define CLASS_DECL __attribute__((__dllimport__)) > #endif > > class __attribute__((__visibility__("default"))) exception_cl : > public virtual std::exception > { > private: > char m_buffer[128]; > public: > int code; > > CLASS_DECL exception_cl(int) ; > virtual CLASS_DECL ~exception_cl() throw() ; > virtual CLASS_DECL const char * what() const throw() ; > }; > > #endif // EXCEPTION_CL_HPP > > Source file exception_cl.cpp > > #define BUILD_SL > #include "exception_cl.hpp" > > CLASS_DECL > exception_cl::exception_cl(int i) : > code(i) > { > m_buffer[0] = '\0'; > } > > CLASS_DECL > exception_cl::~exception_cl() throw() {} > > CLASS_DECL const char * > exception_cl::what( ) const throw() { > return m_buffer; > } > > The command for compiling the source file is: > > g++ -ftemplate-depth-128 -Wno-unused-local-typedefs > -ftrack-macro-expansion=0 -O0 -fno-inline -Wall -g -march=i686 -m32 > -fvisibility-inlines-hidden -fvisibility=hidden -c -o > ".\debug\exception_cl.o" "exception_cl.cpp" > > The command for linking the object file to a shared library called > lib-excl-mgw51 is: > > g++ "-Wl,--out-implib,.\debug\lib-excl-mgw51.dll.a" -o > ".\debug\lib-excl-mgw51.dll" -shared -Wl,--start-group > ".\debug\exception_cl.o" -Wl,-Bstatic -Wl,-Bdynamic -Wl,--end-group > -g -march=i686 -m32 > > These commands succeed without problems in creating the shared library > and the import library in the 'debug' subdirectory. > > Now the source file to be built into an executable, which uses the > exception_cl class from the shared library. I call the source file > 'throw_exception_cl.cpp': > > #include "exception_cl.hpp" > template<class E> void throw_exception(E const & e) { throw e; } > int main(int argc,char * argv[]) > { > if (argc > 1) > { > #if 1 > throw_exception(exception_cl(0)); > #else > throw exception_cl(0); > #endif > } > return 0; > } > > The command for compiling the file is: > > g++ -ftemplate-depth-128 -Wno-unused-local-typedefs > -ftrack-macro-expansion=0 -O0 -fno-inline -Wall -g -march=i686 -m32 -c > -o ".\debug\throw_exception_cl.o" "throw_exception_cl.cpp" > > This command succeeds in creating the object file in the 'debug' > subdirectory. > > Now the command to link the source file's object file into an executable: > > g++ -Wl,-R -Wl,".\debug" -Wl,-rpath-link -Wl,".\debug" -o > ".\debug\te.exe" -Wl,--start-group ".\debug\throw_exception_cl.o" > ".\debug\lib-excl-mgw51.dll.a" -Wl,-Bstatic -Wl,-Bdynamic > -Wl,--end-group -g -march=i686 -m32 > > This command fails with the messages: > > .\debug\throw_exception_cl.o: In function `ZN12exception_clC1ERKS_': > > C:\Programming\VersionControl\modular-boost\libs\serialization\src/exception_cl.hpp:12: > undefined reference to `vtable for exception_cl' > > C:\Programming\VersionControl\modular-boost\libs\serialization\src/exception_cl.hpp:12: > undefined reference to `vtable for exception_cl' > collect2.exe: error: ld returned 1 exit status > > If in the source file immediately above, the "#if 1" line is changed to > "if 0", the link command succeeds without error. But I need it to > succeed as is. > > Please realize that this is all a much boiled down example of the actual > problem that is occurring with mingw-64 gcc-5.1 32-bit compile, but it > shows the problem itself that is occurring in the actual code. The > problem also occurs in the other latest mingw-64 gcc-4.9.2 and 4.8.5 32 > bit releases. > This is exactly what is necessary to fix any problem: a smallest compilable source code example that shows the problem. Thanks for this. The issue is that you are (or GCC is) using an implicitly defined copy constructor, which is not exported. There are two fixes: 1. Make the whole class CLASS_DECL, instead of each function separately (and remove the visibility attribute which I believe is not useful on Windows) class CLASS_DECL exception_cl /*...*/ 2. Add an explicitly export/imported copy constructor which is probably necessary anywas because you're using a char array (if you used std::array<char,128> or just std::string or some fixed-length short string class, there would be no need to memcpy anything) Unfortunately, c++filt seems to be unable to unmangle the undefined reference name, or I would have gotten to this conclusion a lot sooner. Cheers, Ruben > > Any help or suggestions for solving this problem are much appreciated. > > > > > Thanks, > > > > Ruben > > > > > > > > > > On 24 Jul 2015 13:31, "Edward Diener" > > <[email protected] > > <mailto:[email protected]> > > > <mailto:[email protected] > > <mailto:[email protected]>>> wrote: > > > > > > Before attempting to reduce my code to a small enough example > > to post > > > here in its entirety I will give a description of the problem > > to see if > > > anyone has encountered it in general. The problem is purely a > > linker > > > problem. > > > > > > I have an exported class in a shared library, called it XX in > > header > > > file XX.hpp. From an executable's source file, called it > YY.cpp I > > > include the class's header file where the class will show as > > imported > > > and in the code in the source file I throw an exception with > > an instance > > > of the class, as in: > > > > > > throw XX(some_constructor_parameters); > > > > > > This compiles and links without error. > > > > > > If instead I use a template to throw an exception, such as: > > > > > > template<class E> void throw_exception(E const & e) { > > throw e; } > > > > > > and then invoke it from my executable as: > > > > > > throw_exception(XX(some_constructor_parameters)); > > > > > > I receive a linker error of the form: > > > > > > YY.o: In function `SomeDecoratedName': > > > XX.hpp:27: undefined reference to `vtable for XX' > > > XX.hpp:27: undefined reference to `vtable for XX' > > > > > > I realize that this is not a complete example but before > > reducing my > > > code to the least possible example which will reproduce this > > problem I > > > thought I would ask if anyone has encountered anything like > > it, or has > > > any idea why using a template causes a linker error whereas > > not using > > > the template links would link without any problems. > > > > > ------------------------------------------------------------------------------ > _______________________________________________ > Mingw-w64-public mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/mingw-w64-public >
------------------------------------------------------------------------------
_______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
