bgreen
October 12, 2006, 4:50pm
1
The use of variable argument lists is causing an undefined reference in my C++ code. How can I fix this?
I have two source files that use va_args. But each one names std::va_list differently. Passing the output of nm through c++filt, I see this in one of the files:
00000000000022a0 T lib::sappendv(char **, int, char const *, __C1 *)
In the other, I see this:
0000000000002ea0 T lib::Clogger::printv( (int, char const *, __C11 *))
U lib::sappendv(char **, int, char const *, __C11 *)
Why does one source file use __C11, and the other __C1?
bgreen-
__C1 and __C11 look like compiler generated types.
Use pgdecode instead of c++filt to get an accurate C++ demangling: nm t.o | pgdecode
Make sure that you always #include stdarg.h , and not varargs.h. varargs is not
ansi standard, and could cause trouble.
If this does not solve your problem, send us a small example that reproduces the problem so
that we may look into it.
bgreen
October 12, 2006, 7:09pm
3
Here is sample code that demonstrates the problem.
Try to compile these two files into an executable. Note the comment in bug.cxx.
Here is what I get:
$ pgCC bug.cxx bug1.cxx
bug.o: In function `sprint(char const *,...)':
bug.cxx:(.text+0x92): undefined reference to `sprintv(char const *, __C11 *)'
bug.cxx:
#include <string> // comment this line out for a successful build
#include <cstdarg>
char *sprintv(const char *fmt,std::va_list args);
void sprint(const char *fmt,...)
{
va_list args;
va_start(args,fmt);
sprintv(fmt,args);
va_end(args);
}
int main()
{
sprint("%d",1);
}
bug1.cxx:
#include <string>
#include <cstdarg>
char *sprintv(const char *fmt,std::va_list args)
{
char *msgbuf = 0;
return msgbuf;
}
bgreen-
Thank you.
This is a bug in our C++ compiler. I have filed TPR 3976 to track it.
In the mean time, you can change a line our header file /usr/pgi/linux86-64/include/va_list.h
to work around the bug:
*** va_list.h.bad Thu Oct 12 13:19:44 2006
— va_list.h Thu Oct 12 13:20:16 2006
*** 19,25 ****
extern “C” {
#endif /* __cplusplus */
! typedef struct {
unsigned int gp_offset;
unsigned int fp_offset;
char * overflow_arg_area; /* Address of memory args area. /
— 19,25 ----
extern “C” {
#endif / __cplusplus */
! typedef struct __pgi_tag {
unsigned int gp_offset;
unsigned int fp_offset;
char * overflow_arg_area; /* Address of memory args area. */