I am trying to compile my C++ code on a cluster using a different version of gcc; I run into this "undefined reference to vtable" linker error, which doesn't show up when I compile on my local machine.
What I am trying to do is to create a static library for Romberg integration, to be used in my main code. I successfully create the library, and when I compile on my local machine no linker error is reported and the code works just fine. However, when trying to compile on a cluster machine, the following error is displayed, at linking stage:
undefined reference to `vtable for Poly_interp'
I tried to check whether there where some virtual functions left undefined in derived classes, or if a virtual destructor was define, but I couldn't spot any mistake.
These are the part of my code I reckon may be 'indicted':
Makefile
CXX = g++
STANDARD = -std=c++11
[...]
RESULT = ../libraries/libromberg.a
SRC = poly_interp.cpp base_interp.cpp
OBJS := $(SRC:%.cpp=%.o)
HEADERS = $(wildcard *.hpp)
poly_interp.o: recipe_types.hpp base_interp.hpp poly_interp.hpp
base_interp.o: recipe_types.hpp base_interp.hpp
[...]
all: $(RESULT)
$(RESULT): $(OBJS) $(HEADERS)
ar rs $@ $^
[...]
base_interp.hpp
struct Base_interp
{
Int n, mm, jsav, cor, dj;
const Doub *xx, *yy;
Base_interp(VecDoub_I &x, const Doub *y, Int m)
: n(x.size()), mm(m), jsav(0), cor(0), xx(&x[0]), yy(y)
{
dj = MIN(1,(int)pow((Doub)n,0.25));
}
Doub interp(Doub x)
{
Int jlo = cor ? hunt(x) : locate(x);
return rawinterp(jlo,x);
}
Int locate(const Doub x);
Int hunt(const Doub x);
Doub virtual rawinterp(Int jlo, Doub x) = 0;
};
poly_interp.hpp
#include "base_interp.hpp"
struct Poly_interp : Base_interp
{
Doub dy;
Poly_interp(VecDoub_I &xv, VecDoub_I &yv, Int m)
: Base_interp(xv,&yv[0],m), dy(0.) {}
Doub rawinterp(Int jl, Doub x) override;
};
poly_interp.cpp
#include "poly_interp.hpp"
Doub Poly_interp::rawinterp(Int jl, Doub x)
{
Int i,m,ns=0;
Doub y,den,dif,dift,ho,hp,w;
const Doub *xa = &xx[jl], *ya = &yy[jl];
VecDoub c(mm),d(mm);
dif=abs(x-xa[0]);
for (i=0;i<mm;i++)
{
if ((dift=abs(x-xa[i])) < dif)
{
ns=i;
dif=dift;
}
c[i]=ya[i];
d[i]=ya[i];
}
y=ya[ns--];
for (m=1;m<mm;m++)
{
for (i=0;i<mm-m;i++)
{
ho=xa[i]-x;
hp=xa[i+m]-x;
w=c[i+1]-d[i];
if ((den=ho-hp) == 0.0) throw("Poly_interp error");
den=w/den;
d[i]=hp*den;
c[i]=ho*den;
}
y += (dy=(2*(ns+1) < (mm-m) ? c[ns+1] : d[ns--]));
}
return y;
}
Compiler version on my machine:
MacBook-Pro-4:~ macbookpro$ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.11.45.2)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Found CUDA installation: /usr/local/cuda, version unknown
Compiler version on the cluster machine:
mpellegrino@node-5-1 enskog_vlasov_serial $ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/software/matematica/sw/pkgs/toolchains/gcc-glibc/5/prefix/bin/../libexec/gcc/x86_64-mk-linux/5.3.0/lto-wrapper
Target: x86_64-mk-linux
Configured with: ../gcc-5.3.0/configure --build=x86_64-mk-linux --prefix=/u/sw/pkgs/toolchains/gcc-glibc/5/prefix --with-local-prefix=/u/sw/pkgs/toolchains/gcc-glibc/5/base --with-native-system-header-dir=/u/sw/pkgs/toolchains/gcc-glibc/5/prefix/include --with-pkgversion=mk --with-bugurl=https://bitbucket.org/mattiapenati/mk/issues --disable-nls --disable-multilib --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-lto --enable-libgomp --disable-libstdcxx-pch --enable-bootstrap --enable-languages=c,c++,fortran
Thread model: posix
gcc version 5.3.0 (mk)
I solved... no, actually I didn't solve the problem: I by-passed it by putting everything in a header file (so, no poly_interp.o and base_interp.o are created, as well as the static library), but I believe this to be a quite inelegant solution. The full Linker error is the following
/tmp/ccj8ToBh.o: In function `Poly_interp::Poly_interp(std::vector<double, std::allocator<double> > const&, std::vector<double, std::allocator<double> > const&, int)':
/home/matematica/mpellegrino/enskog_vlasov/enskog_vlasov_serial/./romberg/poly_interp.hpp:16: undefined reference to `vtable for Poly_interp'
/tmp/ccj8ToBh.o: In function `double qromb<std::function<double (double)> >(std::function<double (double)>&, double, double, double)':
/home/matematica/mpellegrino/enskog_vlasov/enskog_vlasov_serial/./romberg/romberg.hpp:34: undefined reference to `Poly_interp::rawinterp(int, double)'
collect2: error: ld returned 1 exit status
Makefile:32: recipe for target 'main' failed
make: *** [main] Error 1
Aucun commentaire:
Enregistrer un commentaire