On 7/27/2015 5:00 AM, Ruben Van Boxem wrote:
> 2015-07-27 8:54 GMT+02:00 Edward Diener <eldlistmaili...@tropicsoft.com
> <mailto:eldlistmaili...@tropicsoft.com>>:
>
>     On 7/24/2015 11:13 AM, Ruben Van Boxem wrote:
>      > 2015-07-24 17:03 GMT+02:00 Edward Diener
>     <eldlistmaili...@tropicsoft.com
>     <mailto:eldlistmaili...@tropicsoft.com>
>      > <mailto:eldlistmaili...@tropicsoft.com
>     <mailto:eldlistmaili...@tropicsoft.com>>>:
>     >
>     >     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.

Bravo ! Thank you very much !

>
> Cheers,
>
> Ruben
>
>
>     Any help or suggestions for solving this problem are much appreciated.
>
>     >
>     > Thanks,
>     >
>     > Ruben
>     >
>     >
>     >      >
>     >      > On 24 Jul 2015 13:31, "Edward Diener"
>     >     <eldlistmaili...@tropicsoft.com
>     <mailto:eldlistmaili...@tropicsoft.com>
>     >     <mailto:eldlistmaili...@tropicsoft.com
>     <mailto:eldlistmaili...@tropicsoft.com>>
>     >      > <mailto:eldlistmaili...@tropicsoft.com
>     <mailto:eldlistmaili...@tropicsoft.com>
>      >
>       <mailto:eldlistmaili...@tropicsoft.com
>     <mailto:eldlistmaili...@tropicsoft.com>>>>
>     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
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to