2015-07-24

undefined reference to `vtable for C'

This post intends to be a quick help for anyone who struggles with this error. This error came to me when I tried to compile a larger source code which was already compiling on Windows. It took me more than an hour to figure it out. Here is what I've found, from solution to details.

Possible reasons

  • C.cpp was not compiled.
  • C.o was not added to inputs.
  • There is a virtual method in the C class that is not defined (body of method not present).

Minimalistic reproduction

vtrep.cpp

class C
{
public:
  virtual ~C()
  { }
public:
  virtual int id();
};

int main()
{
  C c;
  return 0;
}

Compilation

$ g++ -c vtrep.cpp -o vtrep.o
$ g++ -o vtrep vtrep.o
vtrep.o: In function `C::~C()':
vtrep.cpp:(.text._ZN1CD2Ev[_ZN1CD5Ev]+0x13): undefined reference to `vtable for C'
vtrep.o: In function `C::C()':
vtrep.cpp:(.text._ZN1CC2Ev[_ZN1CC5Ev]+0xf): undefined reference to `vtable for C'
collect2: error: ld returned 1 exit status

Note that the error messages tell nothing about the id() method.

2015-04-10

Java ArrayList resize

Once I had an array:

    static final Apple[] apples = new Apple[4];

Then circumstances changed so, Apple became generic, so my code changed to

    static final Apple<T>[] apples = new Apple<T>[4];

which produced compile errors as Cannot create a generic array of Apple<T>, so I was forced to switch to ArrayList like:

    static final ArrayList<Apple<T>> apples = new ArrayList<>(4);
    // 4 means capacity here not size.

I have some code in a static initializer block that fills apples using calculated indexes, so it is not a sequence of add(e) calls and it is not desirable for me to rearrange it that way.

I would like to resize the array to have 4 elements, all of them null. A manual way to achieve it is this:

    static {
      for(int i=0; i<4; ++i)
        apples.add(null);
      // ORIGINAL index-magic based code here.
    }

Which is super effective but not so elegant.

Unfortunately all my search efforts on the Internet were derailed because of posts that suggest ensuring capacity and then adding elements with add(e). None of them addressed the original question of resizing an ArrayList using a filler element. The OPs of those questions were satisfied with those answers, but I really would like to have the answer to the original question.

Until then this will go:

  /**
   * Resizes and returns an {@code ArrayList}.
   * Capacity is not freed upon shrinking. At most one allocation happens.
   * 
   * @param list
   *          Input to be altered, return value.
   * @param size
   *          Desired size
   * @param filler
   *          Additional elements - if any - will be set to this.
   * @return Altered list.
   */
  public static <T> ArrayList<T> resize( ArrayList<T> list, int size, T filler ) {
    for( int i = list.size(); i > size; --i )
      list.remove( i - 1 );
    list.ensureCapacity( size );
    for( int i = list.size(); i < size; ++i )
      list.add( filler );
    return list;
  }

  /**
   * Resizes and returns an {@code ArrayList}.
   * Capacity is not freed upon shrinking. At most one allocation happens.
   * Additional elements - if any - will be set to null.
   * 
   * @param list
   *          Input to be altered, return value.
   * @param size
   *          Desired size
   * @return Altered list.
   */
  public static <T> ArrayList<T> resize( ArrayList<T> list, int size ) {
    return resize( list, size, null );
  }

It is slower than the original for based ad-hoc solution, but it is quicker to read at the place of usage, and resizing of arrays do not (should not) happen that often, as I would seriously doubt the general quality of a code where an array resizing takes place at a hot-spot.