Here are a few gotchas.
- If you are working on a local server, you can mix
httpssource files. But if you want to see things on the bl.ocks website, everything needs to be at the same security level. You browser will not tell you about this problem. I would default to
https. For leaflet you need:
whereas D3 is:
- Another thing is that you might want to add some leaflet plugins. These are great but you MUST add the link to the plugin AFTER you have provided the leaflet script, like this:
I’ve been messing about with various visualisation using D3 and leaflet. These tools are great but they interact with a browser and you will want to check your code before sending it to a Gist so that it can be rendered on Bl.ocks.
The links have all the documentation for doing so.
Once you have that installed, you simply navigate to your folder with your website in either a terminal or powershell, and type
http-server. When you are finished, type
DAV - Some notes mainly for my own use - I guess other folk have their favourite debugging methods
When I first started ‘debugging’ I would simply insert
std::cout statements into the code before the suspect line of code that was causing the crash or bug, to get it to print out variable values and so on. Then people started talking about this magical tool called gdb (The GNU debugger), which would run your program for you and then print out the most recent function calls and variables just before your code crashed.
GDB requires you to compile your code in a certain way - you must set any optimisation flags to either
Og, and you need to set the compiler to generate debugging information when it builds the executable. This is done with the
-g flag or even
-ggdb flag to get gdb specific deugging information. So your makefile might look something like this:
To debug your new executable run
gdb ./MyExecutable, note that you don’t specifiy any command line arguments at this stage, as is normally done with the LSDTopoTools executable files. This is done in the next stage, so after gdb loads, type
run [PATH_TO_INPUT_DATA] [PARAMETER_FILE], (or whatever command line arguments and options your executable expects to receive. The program will run as normal, and output the usual stuff to the terminal.
If your program gets to a point where it crashes, however, it will print out the error that terminated the program (often something like
Program received signal SIGSEGV, Segmentation fault), but it will print out the very last function call and tell you the line number of the source code where the fault occurred.
Sometimes, the output is confusing because it doesn’t relate directly to one of your source code files. For example if you have a segmentation fault in the LSDTopoTools code, it may well say that the error took place in one of the TNT/Template Numerical Toolkit library headers. (like
Array2D.h or similar). Since it’s unlikely that the real cause of the bug or crash occurred in one of these library files (though not impossible), you can trace further up the call stack (i.e. list of functions that were called that lead to this crash), by typing
backtrace or just
bt for short.
Hopefully, you should eventually see one of your source code files in the stack trace, and the line number in the corresponding source code file. It will also print the value of any local variables at the line number which are in scope. That is as far as it goes - it won’t tell you exactly where on that line the error happened, but at least it has narrowed it down quickly!
More detailed debugging info
If you want even more debugging information, you can type
backtrace full or
bt full and the debugger and it will print out all the variables in the current scope, as well as all the global variables. Note this is a massive terminal-filling tome of output!
As LSDTopoTools uses a lot of the Standard Template Library functions, (std::vector, std::string, etc…), these can often result in puzzling debug messages. You can get a slightly more comprehensible output by adding the
-D_GLIBCXX_DEBUG flag to your CPPFLAGS in the makefile. If you get the gdb message
missing separate debuginfos or similar, you might need to install a few separate linux packages before you can take advantage of this feature, see this StackOverflow question for more information.
ddd is basically a GUI interface to gdb. It makes it easier to set breakpoints within the code at certain line numbers, or to track whether certain variables change. You can do all of this in plain-old terminal based gdb, but I find ddd a bit easier to use for this kind of stuff.
Valgrind is a really useful tool for finding bugs that gdb/ddd would be unable to do. For example gdb is unable to tell you if you have code that can result in out of bounds array indexing, or might crash due to uninitialised variables, because it can only trace bugs that occur at run time, which may be dependent on the data/DEM or set of parameters you are currently using. Valgrind is better at finding where things might go wrong, even if your program isn’t currently crashing. It’s also used to find memory leaks - i.e. where memory is allocated for a data stucture but never deallocated.
The main things I use Valgrind for:
- Out of bounds array index checking
- Finding conditional statements that are based on variables that might be uninitailised.
- Finding memory leaks.
Valgrind is used with the command
valgrind [VALGRIND OPTIONS] ./MyProg.out [ARGUMENTS] [OPTIONS]
The two most useful options I tend to use with valgrind are
--leak-check=yes (to find memory leaks), and
--track-origins=yes, which gives a bit more detail in where your program crashed/might crash. Both of these options, and valgrind in general, add a considerable amount of memory usage to your program, and run time is general much slower than a standard debugging run with gdb/ddd. However it’s a very useful tool.
Based on email from SMM ages ago and some stuff I read off stack overflow…
Some of the classes/objects in LSDTopoTools rely on access to other objects in different classes. For example, the some of the
LSDIndexRaster member functions take
LSDRaster objects as arguments passed to the functions. One way to make these external classes available is to
#include the relevant header file that conains the class. This is OK, but can lead to problems with circular dependencies if two header files reference each other’s classes.
The solutuion to this cyclical problem is to use a forward-declaration of the class LSDRaster in the LSDIndexRaster.hpp file. Forward-declaration just tells the compiler that this class exists – it doesn’t tell the compiler about any of the class details, but it’s sufficient for the purposes here.
Don’t worry, I haven’t actually changed LSDRaster in the trunk
floats to store it’s data arrays. Floats are fine for more purposes, (they take up less memory than arrays of
doubles for example, and you don’t always need the extra precision of double anyway. But I wanted an
LSDRaster object that used arrays of doubles to maintain compatibility with some other code, so I experimented with the best way of doing this.
Extra data members, overloaded functions
The easiest way is just to create a data member in the LSDRaster class that stores an array of doubles, and then write seperate functions to deal with creating this object, and manipulating it. You can overload functions if they take
TNT::Array2D<float> arguments with the corresponding
Unfortunately, this leads to a lot of code duplication, and extra data members in the LSDRaster class with funny names,
RasterData_dbl, for example. It’s fine, but a bit clunky.
So I figured that it might be possible to create a templated class for LSDRaster. Templates allow a class to be spawned for different data types at run-time. The
TNT::Array2D<> class is an example of a templated class, as you specifiy the data type when you create your object, e.g
TNT::Array2D< int >, or whatever you like.
I had a shot a converting LSDRaster to a template class like so:
So, in theory, we could now create LSDRaster objects with arbitrary type for the array data (Well, not completely arbitrary - it has to be supported by TNT::Array2D.). If we wanted an array of doubles, we could do:
This is good so far, but it raises a few issues. Firstly, the declaration for an
LSDRaster object is now
LSDRaster<typename> and any instance of
LSDRaster in the code will not compile as the typename is incomplete, and your compiler will complain. Secondly, you cannot write the implementation of a template class in a separate
.cpp file, like you can with a normal class. See this SO answer for details. There are ways of getting round this, for example by including the
.cpp file in the header file, and so on.
But anyway, even if we got around the second issue above, there is still the problem that this new LSDRaster<> template has broken everyone’s code that contains any use of
LSDRaster obj. After some more reading, I though it might be possible to use a
typedef to subvert this, and stop everyone’s code from breaking.
typedef just says that we want to use a synonym
LSDRaster to mean
LSDRaster<> without any type given inside the angle brackets, will default to float, as it was specified in the template definition as:
template<typename T = float>)
Unfortunately, you can’t do this within a class - a
typedef can’t have the same name as it’s enclosing class, and we need this inside the class because some of our functions take
LSDRaster objects (or references) as arguments. You also have to put the
typedef in all the other classes that use
The only way of getting around this would be to give the LSDRaster class a different name, something like:
And this would be ok, but you’d still have to change a lot of people’s code…