Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7943 Discussions

Error linking exported templates: undefined reference to `[...]__gnu_cxx27__exchange_and_add_dispatchEPii'

terminatorul
Beginner
2,103 Views

Hello

I installed Intel C++ compiler 11.1 on Ubuntu Linux 9.10 to try the famous export keyword for exporting templates.

I also had to also install gcc-4.2 and g++-4.2 along with gcc-4.4 because icpc could not compile the standard header files with my default gcc-4.4.1, complaing about undeclared symbol __builtin_va_args used to define a variable to hold variable-length arguments list. For that I have to run icpc with --gcc-name=.. and --gxx-name=... options.

Now I wrote a simple C++ programs with a simple exported template (declared in a header file and implemented in a .cc file) but after linking I get this messages:

[plain]main.o: In function `main':
main.cc:(.text+0x2d9): undefined reference to `_ZB30_17_OutputTemplate_cc_6fc53136N9__gnu_cxx27__exchange_and_add_dispatchEPii'
main.cc:(.text+0x31e): undefined reference to `_ZB30_17_OutputTemplate_cc_6fc53136N9__gnu_cxx27__exchange_and_add_dispatchEPii'
main.cc:(.text+0x35d): undefined reference to `_ZB30_17_OutputTemplate_cc_6fc53136N9__gnu_cxx27__exchange_and_add_dispatchEPii'
main.o: In function `std::basic_string, std::allocator >::~basic_string()':
main.cc:(.gnu.linkonce.t._ZNSsD1Ev[.gnu.linkonce.t._ZNSsD1Ev]+0x3f): undefined reference to `_ZB30_17_OutputTemplate_cc_6fc53136N9__gnu_cxx27__exchange_and_add_dispatchEPii'
make: *** [main] Error 1
[/plain]

My command lines to compile and link, modeled after the short export example in the documentation, where:

[bash]icpc \
-gcc-name=gcc-4.2 \
-gxx-name=g++-4.2 \
-gcc-version=424 \
-export \
-export-dir . \
-c \
\
main.cc
icpc \
-gcc-name=gcc-4.2 \
-gxx-name=g++-4.2 \
-gcc-version=424 \
-export \
-export-dir . \
-c \
\
OutputTemplate.cc
icpc \
-gcc-name=gcc-4.2 \
-gxx-name=g++-4.2 \
-gcc-version=424 \
-export \
-export-dir . \
-o main \
\
main.o OutputTemplate.o
[/bash]

(although a singe command to compile and link has the same results and I think is the same thing anyway).

You have my Makefile and sampe source code files attached, they are very simple.

I did sourced /opt/intel/Compiler/11.1/064/bin/iccvars.sh ia32 before running make.

If I explicitly instantiate the needed template in my source files, than the error is gone and the executable can be built.

Do you know what am I doing wrong and why I can not link exported templates ?

I installed the compiler following the instructions in the thread on Ubuntu and Debian instalation for IA32 installation.

Here are my application's versions:

[bash]adrian@adrian-desktop:~/projects/IntelExport$ gcc-4.2 -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.2.4 (Ubuntu 4.2.4-5ubuntu1)
adrian@adrian-desktop:~/projects/IntelExport$ g++-4.2 -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-targets=all --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.2.4 (Ubuntu 4.2.4-5ubuntu1)
adrian@adrian-desktop:~/projects/IntelExport$ icpc -v
Version 11.1
adrian@adrian-desktop:~/projects/IntelExport$ icc -v
Version 11.1
adrian@adrian-desktop:~/projects/IntelExport$ uname -a
Linux adrian-desktop 2.6.31-17-generic #54-Ubuntu SMP Thu Dec 10 16:20:31 UTC 2009 i686 GNU/Linux
adrian@adrian-desktop:~/projects/IntelExport$
adrian@adrian-desktop:~/projects/IntelExport$ icpc --version
icpc (ICC) 11.1 20091130
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

adrian@adrian-desktop:~/projects/IntelExport$ icc --version
icc (ICC) 11.1 20091130
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

adrian@adrian-desktop:~/projects/IntelExport$


[/bash]

0 Kudos
9 Replies
Yuan_C_Intel
Employee
2,103 Views

Hi, user terminatorul

Thank you for submitting this question.

I have gone through your code and reproduced the failure.

I found that you use export keyword both in the template declaration header file and the definition cpp file. I think only cpp file where the export keyword is needed.

However, I tested with the modified code and found an interal error instead. I'll report this issue to our problem tracking system and let you know for any update later on.

Thank you.

0 Kudos
terminatorul
Beginner
2,103 Views

Actually export keyword is only needed in the header file.

Since the .cpp file includes the header, it also includes the prototype declaration there with the export specifier, so it knows the template is to be exported. It is also ok in C++ to specify export again in the .cpp file.

I also got the internal error, but it quickly goes away after the intermediate files (object .o files, .et files, .ti, .tii files) are cleaned, and then I get the expected error message:

[plain]undefined reference to `std::basic_string, std::allocator > makeString(char const*)'
[/plain]

which is normal if you specify export only in the template definition.

I have attached my modified sources again (with a new 'clean' target in the makefile) but the differences from the previously attached sources is not significant ...

Thank you,

Timothy Madden

.

0 Kudos
Yuan_C_Intel
Employee
2,103 Views

Hi, Timothy

Thanks for the correction.Yes, only the header file needs the export keyword, and I also verified the internal error goes away with your updated files. Thanks.

I verified the failure happens due to the usage of std::basic_string. The incorrect reference from the error message, actually refers to function "__gnu_cxx::__exchange_and_add_dispatch" invoked by the basic_string destructor ~basic_string(), see:

  1. main.o:Infunction
  2. `std::basic_string,std::allocator>::~basic_string()':
  3. main.cc:(.gnu.linkonce.t._ZNSsD1Ev[.gnu.linkonce.t._ZNSsD1Ev]+0x3f):undefinedreferenceto
  4. `_ZB30_17_OutputTemplate_cc_6fc53136N9__gnu_cxx27__exchange_and_add_dispatchEPii'

[bash]        void
        _M_dispose(const _Alloc& __a)
        {
#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
          if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
            if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount,
                                                       -1) <= 0)
              _M_destroy(__a);
        }  // XXX MT
[/bash]

From the assembly code generated, seems only this function which is a member of a second class __gun_cxx is mapped incorrectly. Other functions defined under basic_string are correctly mapped.

I'll let you know for other further update. Thanks!

0 Kudos
Judith_W_Intel
Employee
2,103 Views

I verified that your program works if you don't redefine gxx_name and gcc-name.

My guess is you're not linking in the right version of the Gnu libraries.

Instead of working around the lack of the builtin_va_args by setting gxx_name and gcc-name I would try doing -D__builtin_va_arg=va_arg and see if that works.

Also if you're on a supported platform that lack of the va_arg builtin should be reported as a bug.

Judy

0 Kudos
terminatorul
Beginner
2,103 Views

Sorry the error was about __builtin_va_list.

Compilation messages were:

[plain]icpc 
-export
-c

main.cc
/usr/include/c++/4.4.1/i486-linux-gnu/bits/c++locale.h(85): error: identifier "__builtin_va_list" is undefined
__builtin_va_list __args;
^
detected during compilation of secondary translation unit "OutputTemplate.cc"

/usr/include/c++/4.4.1/i486-linux-gnu/bits/c++locale.h(85): error: expected a ";"
__builtin_va_list __args;
^
detected during compilation of secondary translation unit "OutputTemplate.cc"

/usr/include/c++/4.4.1/i486-linux-gnu/bits/c++locale.h(86): error: identifier "__args" is undefined
__builtin_va_start(__args, __fmt);
^
detected during compilation of secondary translation unit "OutputTemplate.cc"

compilation aborted for main.cc (code 2)
[/plain]

If I try to define __builtin_va_list as va_list on the command line I get 'identifier "va_list" is undfined'. Same if I define as _va_list or __va_list.

Anyway I would rather not interfere with gcc internals or built-in symbols, really.

Can I somehow specifiy the directory where gcc-4.2 libraries are installed, like /usr/lib/gcc/i486-linux-gnu/4.2/ ? Trying -cxxlib=/dir also expects to find g++-4.2 under the specified directory, which is not appropriate since g++-4.2 is in /usr/bin.

How do I report this as a bug ?

0 Kudos
terminatorul
Beginner
2,103 Views

Anything else I could try ?

Intel C++ compiler for Linux is the only compiler with export I could try if I want to see the keyword working ...

Could I redefine __builtin_va_list with something else ? Should I uninstall gcc-4.4 ? Can I tell icpc to use some specific gcc libraries ?

Thank you,

Timothy Madden

0 Kudos
Yuan_C_Intel
Employee
2,103 Views

Hi, Timothy Madden

I have reported the bug on __builtin_va_list for you. We will try to resolve this issue as soon as we can. However, please be advised that this issue may have to be targeted to for the next release. I will let you know when I have an update on this issue.

Meanwhile, do you have a need to use type std::basic_string in your template? Could you have a try to use other simple data type such as char *? I tried following template format works fine:

[cpp]export template
        charT *makeString(charT const *szMessage)
        {
            return (charT *)szMessage;
        }
[/cpp]

You also could have a try to uninstall your gcc 4.4.1, and install your gcc 4.2 as your default gcc version, so you won't need use the -gcc-name options. See if the failure still there.

Thank you.

0 Kudos
terminatorul
Beginner
2,103 Views

Thank you !

I never really though it is basic_string template the one triggering the problem.

If it works with charT * instead of basic_string than I will try to use charT *. What I am interested in is the export feature, which unfortunately I have heard is not fully supported ... :(

I have uninstalled all my gcc-4.4/g++-4.4/gcc-4.2/g++-4.2 and then I have compiled and installed gcc/gcc v4.2.0 (I had 4.2.4 previously). Then I tried to compile my example program without -gcc-name, -gxx-name or -cxxlib options.

I get the same undefined symbol errors from the linker even with gcc-4.2.0 installed as the only/default gcc version in my system.

Thank you,

Timothy Madden

0 Kudos
Yuan_C_Intel
Employee
2,103 Views

Hi, Timothy

Thanks for letting me know the result.

The unrecognized "__builtin_va_list"will be fixed in our next major release: 12.0. You can have a try after Intel C++ compiler 12.0 is available.

Thank you.

0 Kudos
Reply