There are a few things you should know before tackling Safer STL:
/export/home/class/util
.
g++
. You cannot use Safer STL on cslab machines with the native CC
compiler; you cannot use Safer STL on Linux machines such as rockhopper. I'm
eventually going to fix it so you can use Safer STL all over the place, but if
you find the current situation intolerable, you should let me know and I'll
try and change things sooner rather than later.
With the preliminaries out of the way, here's how to you get your program to use Safer STL instead of the default STL:
.o
object
files, make sure the compiler picks up the Safer STL versions of the include
files by using the -I
command-line option to add the Safer STL include
directory /export/home/class/util
:
$ g++ -gstabs -c -I/export/home/class/util/include/stlport
your-file-here.cc
If you do not use the -I
option to specify the Safer STL include
directory, the compiler will use the default STL.
You cannot mix Safer STL and the default STL in the same program; you must either compile all your files to use Safer STL or to use the default STL.
The -gstabs
command-line option generates extra information useful for
debugging code. You do not have to specify -gstabs
, but you probably
should. If you do use the -gstabs
option, make sure you use it for all the
files you compile.
You do not have to change your #include
statements to switch between Safer
STL and the default STL. Switching between the two is done by the the -I
option as described above.
$ g++ -gstabs your-files-here.o /export/home/class/util/lib/saferstl.a
The saferstl.a
file is a library containing code implementing various
features of Safer STL, including the iostream classes. This file should be listed
last after all other object files on the command line.
If you compiled your source with the -gstabs
option, you should link them
with the -gstabs
option as shown. If you didn't use -gstabs
during
compilation, you can skip it during linking.
Once your progam is linked to produce an executable, you can run it as you
normally would.
Makefiles can make compiling and linking less onerous; see the example makefile
in /export/home/class/util/misc
.
core
.
$ ./a.out Accessing element 1 in an empty vector. Abort(coredump) $
Assuming you used the g++
compiler and the -gstabs
option, you can use
the gdb
debugger to find out where your code went wrong:
gdb
your-program core
:
$ gdb a.out core GNU gdb 5.2 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "sparc-sun-solaris2.8"... Core was generated by ./a.out. Program terminated with signal 6, Aborted. Reading symbols from /usr/local/lib/libstdc++.so.5...done. Loaded symbols for /usr/local/lib/libstdc++.so.5 Reading symbols from /usr/lib/libm.so.1...done. Loaded symbols for /usr/lib/libm.so.1 Reading symbols from /usr/local/lib/libgcc_s.so.1...done. Loaded symbols for /usr/local/lib/libgcc_s.so.1 Reading symbols from /usr/lib/libc.so.1...done. Loaded symbols for /usr/lib/libc.so.1 Reading symbols from /usr/lib/libdl.so.1...done. Loaded symbols for /usr/lib/libdl.so.1 Reading symbols from /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1...done. Loaded symbols for /usr/platform/SUNW,Ultra-5_10/lib/libc_psr.so.1 #0 0xff21a3dc in _libc_kill () from /usr/lib/libc.so.1 (gdb)
(gdb)
command prompt, type the where
command. This
produces the stack trace of your program that existed when it crashed:
(gdb) where #0 0xff21a3dc in _libc_kill () from /usr/lib/libc.so.1 #1 0xff1b5324 in abort () from /usr/lib/libc.so.1 #2 0x0003fdc4 in _STL::vector<int, _STL::allocator<int> >::_M_range_check(unsigned) const (this=0xffbee778, __n=1) at /export/home/class/cs-509/include/stlport/stl/_vector.h:175 #3 0x0003fc1c in _STL::vector<int, _STL::allocator<int> >::operator[](unsigned) (this=0xffbee778, __n=1) at /export/home/class/cs-509/include/stlport/stl/_vector.h:203 #4 0x00035f74 in main () at t.cc:6 (gdb)
Read the stack trace from the bottom up, starting at main()
, looking for
the point at which you stop recognizing subroutine names. The last subroutine
name you recognize is probably the place you should start looking for the
problem.
In this example, the problem occured in main()
at line 6 in file
t.cc
.
ddd
(dynamic data debugger), which is a graphical
front-end to gdb
.
std:vectorivec; ivec[0] = 1;
std:vectorivec; ivec.back() = 1; int j = ivec.front();
std:vectorivec; ivec.pop_back();
std:vectorivec; ivec.erase(ivec.begin());
As soon as I figure out how to instrument iterators, this test becomes redundant.
std:vectorivec; ivec.erase(ivec.begin(), ivec.back());
I know, I know: this example is legal. But you get the idea. The comment made in the previous example also applies here.
std:string str; str[0] = '!';
getline()
reads don't clear the string.
std:string str; while (!cin.eof()) getline(cin, str)
This is a non-standard change; the standard requires that getline()
clear
the string before the result of reading the input stream is known. Code that
incorrectly tests for eof (as done above) will make an extra pass through the
loop with a non-empty string, which should make it easier to see the error.
This page last modified on 21 January 2004.