Thursday 14 February 2013

When it all goes wrong!

It's that time of year again, (no not Valentines day). Students have finally realised that they have assignments to do and are finally testing and writing code!

So far today I've had 12 email (and this week about 30) with problems and errors, so I've decided to collate as much wisdom and help as I can here which hopefully will help not only you but also me!

This post is intentionally sarcastic and not aimed at anyone in particular!

RTFEM

A lot of the time the errors are quite easy to spot but you get the blind panic of it not working, first thing you should do is "read the (fine) error message".

In the following example
src/GLWindow.cpp: In member function 'void GLWindow::persp(GLWindow::MODE)':
src/GLWindow.cpp:256: error: expected ',' or ';' before 'm_transformStack'
make: *** [obj/GLWindow.o] Error 1
In this case we can read that there is an error in the file src/GLWindow.cpp at line 256 so I would suggest looking there!

As I'm using (and most of you are) QtCreator we only have to double click on the error message to goto the error. Even better it also underlines it in red! (BTW green underlined usually indicates unused variables so we can remove them as well) and yes in this case I've missed a ;

Now some errors are not as obvious and I will add a list of the common ones as I get sent them at the bottom of this post. 

Different Error types

It is important to differentiate between error types.  We can roughly split the errors into three categories.
  1. Compilation errors
  2. Linker errors
  3. Runtime errors
Compilation errors are the most common and may be due to many different factors, some can be due to a missing header / include such as
src/main.cpp: In function 'int main(int, char**)':
src/main.cpp:11: error: 'MainWindow' was not declared in this scope
src/main.cpp:11: error: expected `;' before 'w'
src/main.cpp:13: error: 'w' was not declared in this scope
make: *** [obj/main.o] Error 1
In this case we are just missing the #include "MainWindow.h" but the error seems worse, the clue is the "not declared in this scope" which should give you a hint that the compiler doesn't know about something. Another error along the same lines is the following
int main()
{
  std::cout<<"hello world\n";
}
In this case we get the error
1.cpp: In function 'int main()':
1.cpp:3: error: 'cout' is not a member of 'std'
Just because we are missing the #include <iostream>. When you do get these errors this is a good resource for finding out what has gone wrong as is this

Linker errors are harder to find but usually are due to the fact that you don't have the correct libraries installed, the also seem much more scary as they seem to go on forever in some cases

For example the following
clang++ -Wall -g ClearScreen.cpp -o ClearScreen `sdl-config --cflags`
Undefined symbols for architecture x86_64:
  "_SDL_FillRect", referenced from:
      clearScreen(SDL_Surface*, char, char, char) in ClearScreen-vFrFBN.o
  "_SDL_Flip", referenced from:
      clearScreen(SDL_Surface*, char, char, char) in ClearScreen-vFrFBN.o
  "_SDL_Init", referenced from:
      _SDL_main in ClearScreen-vFrFBN.o
  "_SDL_MapRGB", referenced from:
      clearScreen(SDL_Surface*, char, char, char) in ClearScreen-vFrFBN.o
  "_SDL_PollEvent", referenced from:
      _SDL_main in ClearScreen-vFrFBN.o
  "_SDL_Quit", referenced from:
      _SDL_main in ClearScreen-vFrFBN.o
  "_SDL_SetVideoMode", referenced from:
      _SDL_main in ClearScreen-vFrFBN.o
  "_SDL_WM_SetCaption", referenced from:
      _SDL_main in ClearScreen-vFrFBN.o
  "_main", referenced from:
     -u command line option
     (maybe you meant: _SDL_main)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
This is due to the fact that the compiler is not using the SDL libs flags "-L/usr/local/lib -lSDLmain -lSDL" Once these are added it usually fixes things. One of the most difficult problems you will encounter is finding which function lives in which lib, again you can google. Or I have a handy shell script
#!/bin/bash
for f in *.a *.so *.dylib
do
  echo "checking for $1 in - $f"
  strings $f | grep $1
done
Which using checkLib.sh glVertex in the directory /usr/lib/ gives
checkLib.sh glVertex | more
checking for glVertex in - libGLEW.a
glVertexAttrib1dNV
glVertexAttrib1dvNV
glVertexAttrib1fNV
glVertexAttrib1fvNV
....
Runtime errors are usually created when we cant find the dynamic libs we need to link to, for example
dyld: Library not loaded: libNGL.1.0.0.dylib
  Referenced from: /Volumes/home/jmacey/teaching/NGL5Demos/SimpleNGL/./SimpleNGL
  Reason: image not found
Trace/BPT trap: 5
Means that the LD_LIBRARY_PATH (actually DYLD on mac) has not been set for the NGL lib (see here)

If in doubt make clean

Sometimes things get out of sync and dependancies are not re-read. The simplest solution is to do a qmake; make clean ; make;l

In QtCreator this is the same as doing a re-build all. You will be surprised how often this solves things (usually to deps not being updated)

Still Stuck do this

If you need to send me some errors, please don't do this 
Yes that is an iPhone photo of the error message on my monitor, yes I have had this mailed to me before, and no I can't figure out what is wrong! My eyesight used to be that good but not anymore!

This is not much better
Yes I can see the errors in this one but it still doesn't help much, I really need to see the compiler output / flags as well as the error messages (these are on different tabs on Qt).

The easiest way of sending me errors etc is via plain ASCII text (I'm old fashioned like that ;-) To do this will require a little typing.

cd [your project root]
make &>err.txt

If you do this in the root of the project where the makefile is it will run make and output all of the errors to the file err.txt. Mail it to me as this will then help me to find the errors.

Send me the code

If I ask you to send me the code, I only need the source and other files not the .o and exe. The easiest way of sending this to me is as follows

cd [your project root]
make distclean
cd ..
tar vfcz code.tgz [your project root]

Then mail me the code, it also helps if I have the following information
  • Operating System (and version if Mac or Linux)
  • Compiler used (use g++ -v or clang -v) 
  • Graphics Card Make Model and version of OpenGL drivers installed. 
  • Versions of any extra libs etc you may be using. 
A lot of the time this could be the cause of the problem, I will test all my code against Mac OSX (Mountain Lion) using

clang++ ( Apple clang version 4.0 (tags/Apple/clang-421.0.60) (based on LLVM 3.1svn) Target: x86_64-apple-darwin12.2.0 Thread model: posix)

and the lab build

clang++ -v clang version 3.2 (trunk 163783) Target: x86_64-unknown-linux-gnu Thread model: posix g++ -v Using built-in specs. Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux Thread model: posix gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)

Also make sure you have pulled the latest versions of any of my code using a bzr pull as I do bug fixes as they are reported (there will soon be a more official way of reporting this using the redmine system)

Some Common Errors (and Fixes)

I get quite a lot of common errors so I will try and list them here

GLEW Errors

If you get something like this
/usr/include/GL/glew.h:84:2: error: gl.h included before glew.h
#error gl.h included before glew.h
 ^
/usr/include/GL/glew.h:90:2: error: glext.h included before glew.h
#error glext.h included before glew.h
It is due to the GLEW libs not being included properly (you may also get lots of PFNGL..... errors as well) Some of the old versions of my .pro files have a subtle bug in them where the defines are not done correctly check the .pro file and make sure this is correct
linux-g++*{
            DEFINES += LINUX
            LIBS+= -lGLEW
}
linux-clang* {
              DEFINES += LINUX
              LIBS+= -lGLEW
}

xxx does not name a type

Errors such as include/GLWindow.h:50: error: ‘Vector’ in namespace ‘ngl’ does not name a type means that you have either not included the correct header or something is missing. In this case it is due to the fact that ngl::Vector has now been replaced with ngl::Vec3 so you will need to #include <ngl/Vec3.h> and also replace all versions of ngl::Vector with ngl::Vec3