imported lab skeletons
This commit is contained in:
parent
4fc8b6c771
commit
e4df45f4a9
47 changed files with 15122 additions and 87 deletions
81
lab1/buggy_programs/CMakeLists.txt
Normal file
81
lab1/buggy_programs/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# An example CMakeLists.txt for the sanitizers example, showing how to
|
||||
# enable sanitizers in a debug build.
|
||||
# It uses generator expressions, to set additional flags when the build type
|
||||
# is Debug.
|
||||
#
|
||||
# To try this out, first create a build directory for a release build,
|
||||
# and do a release build, e.g.,
|
||||
# % mkdir build-rel
|
||||
# % cd build-rel
|
||||
# % cmake SRC_DIR -DCMAKE_BUILD_TYPE=Release
|
||||
# % make
|
||||
#
|
||||
# Run the examples and see that they crash.
|
||||
#
|
||||
# Then create another build directory and do a debug build:
|
||||
#
|
||||
# % mkdir build-dbg
|
||||
# % cd build-dbg
|
||||
# % cmake SRC_DIR -DCMAKE_BUILD_TYPE=Debug
|
||||
# % make
|
||||
#
|
||||
# where SRC_DIR is the directory containing the source and CMakeLists.txt,
|
||||
# e.g., .. if your build directories are placed in this directory.
|
||||
#
|
||||
# Run the examples and verify that the sanitizers find the errors.
|
||||
#
|
||||
# If you want to see the actual commands run during the build, for instance
|
||||
# to verify that the correct compiler flags are used, you can do
|
||||
#
|
||||
# % make VERBOSE=1
|
||||
|
||||
|
||||
cmake_minimum_required (VERSION 3.5)
|
||||
project (Sanitizers)
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
|
||||
# The three standard build types are Release, Debug, and RelWithDebInfo.
|
||||
# If set here, it forces that build type.
|
||||
#
|
||||
# set(CMAKE_BUILD_TYPE Release)
|
||||
# set build type to DEBUG
|
||||
# set(CMAKE_BUILD_TYPE Debug)
|
||||
# or to get an optimized build w/ debug symbols
|
||||
# set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
|
||||
# add the executables
|
||||
add_executable(leak leak.cc)
|
||||
add_executable(bounds bounds.cc)
|
||||
add_executable(bounds-heap bounds-heap.cc)
|
||||
add_executable(ub ub.cc)
|
||||
add_executable(dangling dangling.cc)
|
||||
add_executable(sum sum.cc)
|
||||
add_executable(sum_alt sum.cc)
|
||||
|
||||
# set compiler flag to turn off optimization (for all builds)
|
||||
# add_compile_options("-O0")
|
||||
# or use generator expressions to set flags in debug builds
|
||||
add_compile_options($<$<CONFIG:Debug>:-O0>)
|
||||
|
||||
# set compiler and linker flags to enable the relevant sanitizer
|
||||
target_compile_options(leak PUBLIC $<$<CONFIG:Debug>:-fsanitize=leak>)
|
||||
target_link_libraries(leak $<$<CONFIG:Debug>:-fsanitize=leak>)
|
||||
|
||||
target_compile_options(bounds PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
target_link_libraries(bounds $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
|
||||
target_compile_options(bounds-heap PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
target_link_libraries(bounds-heap $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
|
||||
target_compile_options(ub PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined>)
|
||||
target_link_libraries(ub $<$<CONFIG:Debug>:-fsanitize=undefined>)
|
||||
|
||||
target_compile_options(dangling PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
target_link_libraries(dangling $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
|
||||
target_compile_options(sum PUBLIC $<$<CONFIG:Debug>:-fsanitize=undefined>)
|
||||
target_link_libraries(sum $<$<CONFIG:Debug>:-fsanitize=undefined>)
|
||||
|
||||
target_compile_options(sum_alt PUBLIC $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
target_link_libraries(sum_alt $<$<CONFIG:Debug>:-fsanitize=address>)
|
||||
|
||||
40
lab1/buggy_programs/Makefile
Normal file
40
lab1/buggy_programs/Makefile
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Define the compiler and the linker. The linker must be defined since
|
||||
# the implicit rule for linking uses CC as the linker. g++ can be
|
||||
# changed to clang++.
|
||||
CXX = g++
|
||||
CC = $(CXX)
|
||||
|
||||
# Define preprocessor, compiler, and linker flags. Uncomment the # lines
|
||||
# if you use clang++ and wish to use libc++ instead of GNU's libstdc++.
|
||||
# -g is for debugging.
|
||||
CPPFLAGS = -std=c++11 -I.
|
||||
CXXFLAGS = -O0 -Wall -Wextra -pedantic-errors -Wold-style-cast
|
||||
CXXFLAGS += -std=c++11
|
||||
CXXFLAGS += -g
|
||||
LDFLAGS = -g
|
||||
# CPPFLAGS += -stdlib=libc++
|
||||
# CXXFLAGS += -stdlib=libc++
|
||||
# LDFLAGS += -stdlib=libc++
|
||||
|
||||
PROGS=ub leak bounds bounds-heap dangling sum
|
||||
|
||||
ALL: $(PROGS)
|
||||
|
||||
leak: leak.cc
|
||||
|
||||
dangling: dangling.cc
|
||||
|
||||
bounds: bounds.cc
|
||||
|
||||
ub: ub.cc
|
||||
|
||||
sum: sum.cc
|
||||
|
||||
# Targets
|
||||
# Phony targets
|
||||
.PHONY: all clean test
|
||||
|
||||
# Standard clean
|
||||
clean:
|
||||
-rm $(PROGS)
|
||||
-rm -r $(addsuffix .dSYM, $(PROGS))
|
||||
58
lab1/buggy_programs/Makefile.sanitizers
Normal file
58
lab1/buggy_programs/Makefile.sanitizers
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Define the compiler and the linker. The linker must be defined since
|
||||
# the implicit rule for linking uses CC as the linker. g++ can be
|
||||
# changed to clang++.
|
||||
CXX = g++
|
||||
CC = $(CXX)
|
||||
|
||||
# Define preprocessor, compiler, and linker flags. Uncomment the # lines
|
||||
# if you use clang++ and wish to use libc++ instead of GNU's libstdc++.
|
||||
# -g is for debugging.
|
||||
CPPFLAGS = -std=c++11 -I.
|
||||
CXXFLAGS = -O0 -Wall -Wextra -pedantic-errors -Wold-style-cast
|
||||
CXXFLAGS += -std=c++11
|
||||
CXXFLAGS += -g
|
||||
LDFLAGS = -g
|
||||
# CPPFLAGS += -stdlib=libc++
|
||||
# CXXFLAGS += -stdlib=libc++
|
||||
# LDFLAGS += -stdlib=libc++
|
||||
|
||||
PROGS=ub leak bounds bounds-heap dangling sum sum-alt bounds-alt bounds-heap-alt
|
||||
|
||||
ALL: $(PROGS)
|
||||
|
||||
leak: leak.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=leak -o $@ $<
|
||||
|
||||
dangling: dangling.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
|
||||
|
||||
bounds: bounds.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
|
||||
|
||||
bounds-heap: bounds-heap.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
|
||||
|
||||
bounds-alt: bounds.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
|
||||
|
||||
bounds-heap-alt: bounds-heap.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
|
||||
|
||||
ub: ub.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
|
||||
|
||||
sum: sum.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=undefined -o $@ $<
|
||||
|
||||
sum-alt: sum.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fsanitize=address -o $@ $<
|
||||
|
||||
# Targets
|
||||
# Phony targets
|
||||
.PHONY: all clean
|
||||
|
||||
# Standard clean
|
||||
clean:
|
||||
-rm $(PROGS)
|
||||
-rm -r $(addsuffix .dSYM, $(PROGS))
|
||||
|
||||
64
lab1/buggy_programs/README.txt
Normal file
64
lab1/buggy_programs/README.txt
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
This directory contains a few small examples of how the google sanitizers
|
||||
can be used to find problems related to memory management and undefined behaviour.
|
||||
The sanitizers are libraries that are used to instrument your programs, which is
|
||||
done by compiling and linking with the option -fsanitize=<SANITIZER>.
|
||||
|
||||
For building this example includes two makefiles, one for building without
|
||||
sanitizers (Makefile) and one for building with them (Makefile.sanitizers).
|
||||
Also included is a CMakeListst.txt which uses sanitizers when doing a debug build.
|
||||
|
||||
Examples:
|
||||
|
||||
The file leak.cc contains an example of a memory leak.
|
||||
|
||||
The files bounds.cc, bounds-heap.cc and sum.cc contain examples of accessing
|
||||
outside the bounds of an array (on the stack and on the heap).
|
||||
|
||||
The file dangling.cc contains an example of using a dangling pointer.
|
||||
|
||||
The file ub.cc contains an example of undefined behaviour.
|
||||
|
||||
Demonstration:
|
||||
|
||||
First build the programs using Makefile, and run them.
|
||||
|
||||
Then, first do make clean and then build them using Makefile.sanitizers
|
||||
(make -f Makefile.sanitizers)
|
||||
|
||||
Run the programs again, and see if the errors are detected. Try to understand
|
||||
the diagnostics pringed when the sanitizer detects an error.
|
||||
|
||||
Note that the different sanitizers may produce different error messages
|
||||
for the same problem. Compare the output from sum and sum_alt (which are
|
||||
built from the same source file, but with different sanitizers.)
|
||||
|
||||
This example also includes a CMakeLists.txt that illustrates how to enable
|
||||
the sanitizers for debug builds.
|
||||
|
||||
Building with cmake:
|
||||
|
||||
With cmake, make debug and release builds and compare, typically in
|
||||
separate build directories:
|
||||
|
||||
For the release build:
|
||||
% mkdir build-rel
|
||||
% cd build-rel
|
||||
% cmake -DCMAKE_BUILD_TYPE=Release SRC_DIR
|
||||
% make
|
||||
|
||||
For the debug build:
|
||||
% mkdir build-rel
|
||||
% cd build-rel
|
||||
% cmake -DCMAKE_BUILD_TYPE=Debug SRC_DIR
|
||||
% make
|
||||
|
||||
Both gcc and clang use the google sanitizers, but different compiler versions
|
||||
may use different versions of the sanitizers. If you have installed a more recent
|
||||
compiler version, you may need to tell cmake to use that.
|
||||
By default, cmake will use the system's default compiler. To specify which
|
||||
compiler to use, you can add (for gcc)
|
||||
-DCMAKE_CXX_COMPILER=g++
|
||||
-DCMAKE_C_COMPILER=gcc
|
||||
or, for clang:
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
25
lab1/buggy_programs/bounds-heap.cc
Normal file
25
lab1/buggy_programs/bounds-heap.cc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <memory>
|
||||
using std::cout;
|
||||
|
||||
|
||||
void print(int* a, int size)
|
||||
{
|
||||
for(int i=0; i < size; ++i){
|
||||
cout << a[i] << " ";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
|
||||
void example()
|
||||
{
|
||||
std::unique_ptr<int[]> xs(new int[10]);
|
||||
std::iota(xs.get(), xs.get()+10, 0);
|
||||
print(xs.get(), 15);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
example();
|
||||
}
|
||||
24
lab1/buggy_programs/bounds.cc
Normal file
24
lab1/buggy_programs/bounds.cc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <iostream>
|
||||
#include <numeric>
|
||||
using std::cout;
|
||||
|
||||
|
||||
void print(int* a, int size)
|
||||
{
|
||||
for(int i=0; i < size; ++i){
|
||||
cout << a[i] << " ";
|
||||
}
|
||||
cout << "\n";
|
||||
}
|
||||
|
||||
void example()
|
||||
{
|
||||
int xs[10];
|
||||
std::iota(xs, xs+10, 0);
|
||||
print(xs, 15);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
example();
|
||||
}
|
||||
37
lab1/buggy_programs/dangling.cc
Normal file
37
lab1/buggy_programs/dangling.cc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <iostream>
|
||||
#include <numeric>
|
||||
using std::cout;
|
||||
|
||||
struct Foo{
|
||||
Foo(int s) :p(new int[s]), sz(s) {}
|
||||
~Foo() {delete[] p;}
|
||||
int* begin() {return p;}
|
||||
int* end() {return begin()+sz;}
|
||||
const int* begin() const {return p;}
|
||||
const int* end() const {return begin()+sz;}
|
||||
int* p;
|
||||
int sz;
|
||||
};
|
||||
|
||||
void print(Foo f)
|
||||
{
|
||||
for(const auto& x : f) cout << x << " ";
|
||||
endl(cout);
|
||||
}
|
||||
void example1()
|
||||
{
|
||||
Foo f(10);
|
||||
std::iota(std::begin(f), std::end(f), 0);
|
||||
|
||||
print(f);
|
||||
cout << "after first print\n";
|
||||
*f.begin()=123;
|
||||
cout << "printing again\n";
|
||||
print(f);
|
||||
cout << "done\n";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
example1();
|
||||
}
|
||||
29
lab1/buggy_programs/leak.cc
Normal file
29
lab1/buggy_programs/leak.cc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <iostream>
|
||||
using std::cout;
|
||||
|
||||
struct Foo{
|
||||
Foo(int s) :p{new int[s]} {}
|
||||
int* p;
|
||||
};
|
||||
|
||||
struct Bar{
|
||||
Bar(int x) :f(x) {}
|
||||
Foo f;
|
||||
};
|
||||
|
||||
void example1()
|
||||
{
|
||||
Foo f(10);
|
||||
{
|
||||
cout << "entering inner block\n";
|
||||
Bar b(20);
|
||||
cout << "leaving inner block\n";
|
||||
}
|
||||
cout << "leaving example1\n";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
example1();
|
||||
cout << "leaving main\n";
|
||||
}
|
||||
20
lab1/buggy_programs/sum.cc
Normal file
20
lab1/buggy_programs/sum.cc
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include <iostream>
|
||||
|
||||
#define N (4)
|
||||
|
||||
int x = 1000;
|
||||
int a[]{ 1, 2, 3, 4 };
|
||||
int y = 2000;
|
||||
|
||||
int main()
|
||||
{
|
||||
int sum{0};
|
||||
|
||||
std::cout << "welcome to the buggy sum program. the sum should be 10\n";
|
||||
|
||||
for (int i = 0; i <= N; i++)
|
||||
sum += a[i];
|
||||
|
||||
std::cout << "sum = " << sum << "\n";
|
||||
return 0;
|
||||
}
|
||||
31
lab1/buggy_programs/ub.cc
Normal file
31
lab1/buggy_programs/ub.cc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <numeric>
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
std::vector<int> create_vector(int s)
|
||||
{
|
||||
assert(s >= 0);
|
||||
std::vector<int> res(s);
|
||||
}
|
||||
|
||||
template <typename C>
|
||||
void print_seq(const C& c)
|
||||
{
|
||||
for(const auto& x : c) cout << x << " ";
|
||||
cout << "\n";
|
||||
}
|
||||
|
||||
void example()
|
||||
{
|
||||
auto v = create_vector(10);
|
||||
std::iota(begin(v), end(v), 0);
|
||||
print_seq(v);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
example();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue