imported lab skeletons
This commit is contained in:
parent
4fc8b6c771
commit
e4df45f4a9
47 changed files with 15122 additions and 87 deletions
17
lab1/Makefile
Normal file
17
lab1/Makefile
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# The following rule means: "if test_editor does not exist, or
|
||||
# is older than test_editor.o or editor.o,
|
||||
# then link test_editor".
|
||||
test_editor: test_editor.o editor.o
|
||||
g++ -o test_editor test_editor.o editor.o
|
||||
|
||||
# Rules to create the object files.
|
||||
test_editor.o: test_editor.cc editor.h
|
||||
g++ -c test_editor.cc -std=c++11
|
||||
editor.o: editor.cc editor.h
|
||||
g++ -c editor.cc -std=c++11
|
||||
|
||||
print_argv: print_argv.o
|
||||
g++ -o print_argv print_argv.o
|
||||
print_argv.o: print_argv.cc
|
||||
g++ -c print_argv.cc -std=c++11
|
||||
|
||||
50
lab1/MakefileWithDeps
Normal file
50
lab1/MakefileWithDeps
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# 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)
|
||||
|
||||
# Generate dependencies in *.d files
|
||||
DEPFLAGS = -MT $@ -MMD -MP -MF $*.d
|
||||
|
||||
# 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 = -O2 -Wall -Wextra -pedantic-errors -Wold-style-cast
|
||||
CXXFLAGS += -std=c++11
|
||||
CXXFLAGS += -g
|
||||
CXXFLAGS += $(DEPFLAGS)
|
||||
LDFLAGS = -g
|
||||
#CPPFLAGS += -stdlib=libc++
|
||||
#CXXFLAGS += -stdlib=libc++
|
||||
#LDFLAGS += -stdlib=libc++
|
||||
|
||||
# Targets
|
||||
PROGS = test_editor test_coding print_argv
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
test: test_coding test_editor
|
||||
./test_coding
|
||||
./test_editor
|
||||
|
||||
# Targets rely on implicit rules for compiling and linking
|
||||
print_argv: print_argv.o
|
||||
test_editor: test_editor.o editor.o
|
||||
test_coding: test_coding.o coding.o
|
||||
|
||||
# Phony targets
|
||||
.PHONY: all test clean distclean
|
||||
|
||||
# Standard clean
|
||||
clean:
|
||||
rm -f *.o $(PROGS)
|
||||
|
||||
distclean: clean
|
||||
rm *.d
|
||||
|
||||
|
||||
# Include the *.d files
|
||||
SRC = $(wildcard *.cc)
|
||||
-include $(SRC:.cc=.d)
|
||||
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();
|
||||
}
|
||||
44
lab1/cmake-example/CMakeLists.txt
Normal file
44
lab1/cmake-example/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
cmake_minimum_required (VERSION 3.5)
|
||||
project (Simple)
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
|
||||
# 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 library to the include file search path
|
||||
include_directories ("${PROJECT_SOURCE_DIR}/testlib")
|
||||
|
||||
add_subdirectory (testlib)
|
||||
|
||||
# set compiler and linker flags
|
||||
add_compile_options("-Og")
|
||||
#add_compile_options("-fsanitize=address")
|
||||
#link_libraries("-fsanitize=address")
|
||||
|
||||
# add the executable SimpleMain and its dependency on TestLib
|
||||
add_executable(SimpleMain main.cc)
|
||||
target_link_libraries (SimpleMain TestLib)
|
||||
|
||||
##################### Optional features below this line ############
|
||||
|
||||
# The version number. This is not needed but included
|
||||
# to show how information can be passed from CMakeLists.txt
|
||||
# to the program.
|
||||
set (Simple_VERSION_MAJOR 1)
|
||||
set (Simple_VERSION_MINOR 0)
|
||||
|
||||
# configure a header file to pass some of the CMake settings
|
||||
# to the source code. Only needed if we want to pass some
|
||||
# information or configuration from Cmake to the program
|
||||
# being built.
|
||||
configure_file (
|
||||
"${PROJECT_SOURCE_DIR}/SimpleConfig.h.in"
|
||||
"${PROJECT_BINARY_DIR}/SimpleConfig.h"
|
||||
)
|
||||
|
||||
# add the binary tree to the search path for include files
|
||||
# so that we will find SimpleConfig.h
|
||||
include_directories("${PROJECT_BINARY_DIR}")
|
||||
|
||||
35
lab1/cmake-example/README
Normal file
35
lab1/cmake-example/README
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
This is an example project that is built with cmake.
|
||||
The project consists of
|
||||
- an example library, TestLib, which is built from testlib/foo.h and .cc
|
||||
- a configuration file, SimpleConfig.h which is built from SimpleConfig.h.in
|
||||
- a main program, in main.cc
|
||||
|
||||
With cmake, you usually build the project in a directory separate from the source,
|
||||
typically named build. This has the advantages that you can easily make several
|
||||
separate builds simply by doing them in separate build directories. It also
|
||||
means that the generated files are kept separate from the source code, so that
|
||||
removing them is done by simply removing the entire build directory.
|
||||
|
||||
The steps to create the build files (Makefile, unless otherwise specified, but
|
||||
cmake can generate project files for other build systems as well) and then
|
||||
build the project are
|
||||
|
||||
> mkdir build
|
||||
> cd build
|
||||
> cmake ..
|
||||
> make
|
||||
|
||||
To see the actual commands executed when building with the generated Makefile,
|
||||
use the command
|
||||
> make VERBOSE=1
|
||||
|
||||
Configuration of the compilation can be done by setting environment variables
|
||||
which are read by cmake.
|
||||
|
||||
To set which compiler to use:
|
||||
|
||||
CC=clang CXX=clang++ cmake ..
|
||||
|
||||
To set compiler flags, one can use
|
||||
|
||||
cmake -DCMAKE_CXX_FLAGS="-Wall -Werror" ..
|
||||
3
lab1/cmake-example/SimpleConfig.h.in
Normal file
3
lab1/cmake-example/SimpleConfig.h.in
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// the configured options and settings for simple
|
||||
#define Simple_VERSION_MAJOR @Simple_VERSION_MAJOR@
|
||||
#define Simple_VERSION_MINOR @Simple_VERSION_MINOR@
|
||||
25
lab1/cmake-example/main.cc
Normal file
25
lab1/cmake-example/main.cc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include <iostream>
|
||||
#include "SimpleConfig.h"
|
||||
#include "foo.h"
|
||||
#include "bar.h"
|
||||
|
||||
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
/* A small example of a project built using CMake.
|
||||
* The Simple_VERSION_* variables are included
|
||||
* to show how a header file with configuration macros
|
||||
* can be generated from the CMakeLists.txt.
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
cout << "This is version " << Simple_VERSION_MAJOR << "." <<
|
||||
Simple_VERSION_MINOR << "\n";
|
||||
cout << "Hello, world!\n";
|
||||
foo_fun();
|
||||
bar_fun(42);
|
||||
}
|
||||
|
||||
|
||||
1
lab1/cmake-example/testlib/CMakeLists.txt
Normal file
1
lab1/cmake-example/testlib/CMakeLists.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
add_library(TestLib foo.cc bar.cc)
|
||||
6
lab1/cmake-example/testlib/bar.cc
Normal file
6
lab1/cmake-example/testlib/bar.cc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include <iostream>
|
||||
|
||||
void bar_fun(int x)
|
||||
{
|
||||
std::cout << "[bar: " << x << "]" << "\n";
|
||||
}
|
||||
1
lab1/cmake-example/testlib/bar.h
Normal file
1
lab1/cmake-example/testlib/bar.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
void bar_fun(int);
|
||||
7
lab1/cmake-example/testlib/foo.cc
Normal file
7
lab1/cmake-example/testlib/foo.cc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#include <iostream>
|
||||
|
||||
void foo_fun()
|
||||
{
|
||||
auto x = 17; // use a C++11 feature to see if flags are set correctly
|
||||
std::cout << "[foo: " << x << "]" << "\n";
|
||||
}
|
||||
1
lab1/cmake-example/testlib/foo.h
Normal file
1
lab1/cmake-example/testlib/foo.h
Normal file
|
|
@ -0,0 +1 @@
|
|||
void foo_fun();
|
||||
10
lab1/coding.cc
Normal file
10
lab1/coding.cc
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#include<coding.h>
|
||||
|
||||
unsigned char encode(unsigned char c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
unsigned char decode(unsigned char c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
6
lab1/coding.h
Normal file
6
lab1/coding.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __CODING_H
|
||||
#define __CODING_H
|
||||
|
||||
unsigned char encode(unsigned char c);
|
||||
unsigned char decode(unsigned char c);
|
||||
#endif
|
||||
16
lab1/editor.cc
Normal file
16
lab1/editor.cc
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include "editor.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
using size_type = Editor::size_type;
|
||||
|
||||
size_type Editor::get_size() const
|
||||
{
|
||||
return text.size();
|
||||
}
|
||||
|
||||
size_type Editor::find_left_par(size_type pos) const {
|
||||
return string::npos;
|
||||
}
|
||||
27
lab1/editor.h
Normal file
27
lab1/editor.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef EDITOR_H
|
||||
#define EDITOR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class Editor {
|
||||
public:
|
||||
using size_type = std::string::size_type;
|
||||
/* Creates a text editor containing the text t */
|
||||
Editor(const std::string& t) : text(t) {}
|
||||
|
||||
/* Get the size of the current contents */
|
||||
size_type get_size() const;
|
||||
|
||||
/*
|
||||
* Text[pos] contains a right parentheses. Returns the position of
|
||||
* the corresponding left parentheses, or string::npos if there
|
||||
* is no match.
|
||||
*/
|
||||
size_type find_left_par(size_type pos) const;
|
||||
|
||||
// ... functions to edit the text (insert and delete characters)
|
||||
private:
|
||||
std::string text;
|
||||
};
|
||||
|
||||
#endif
|
||||
25
lab1/file_io_example.cc
Normal file
25
lab1/file_io_example.cc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include"coding.h"
|
||||
#include<iostream>
|
||||
#include <iomanip>
|
||||
#include<fstream>
|
||||
|
||||
void print_bytes(std::string infile)
|
||||
{
|
||||
std::ifstream in{infile};
|
||||
|
||||
int c;
|
||||
while((c = in.get()) != EOF ) {
|
||||
std::cout << "read: " << std::setw(3) << c << " [" << char(c) << "]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << argv[0] << " filename" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
print_bytes(argv[1]);
|
||||
return 0;
|
||||
}
|
||||
29
lab1/print_argv.cc
Normal file
29
lab1/print_argv.cc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
/* Example program, printing command line arguments
|
||||
* It is good practice to convert the C string
|
||||
* i.e., "pointer to first element of a null-terminated
|
||||
* array of char" to a std::string and then use the
|
||||
* safer std::string instead of directly using the C-string.
|
||||
*/
|
||||
|
||||
void print_string(std::string str)
|
||||
{
|
||||
cout << "[" << str << "] ";
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
cout << "argc=" << argc << endl;
|
||||
|
||||
for(int i=0; i != argc; ++i){
|
||||
std::string arg{argv[i]}; // create a std::string for the argument
|
||||
|
||||
print_string(arg); // pass the std::string to a functio
|
||||
}
|
||||
cout << endl;
|
||||
return 0;
|
||||
}
|
||||
6
lab1/separate_fn.cc
Normal file
6
lab1/separate_fn.cc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include <iostream>
|
||||
|
||||
void the_function(const std::string& s)
|
||||
{
|
||||
std::cout << "the_function: " << s << "\n";
|
||||
}
|
||||
3
lab1/separate_fn.h
Normal file
3
lab1/separate_fn.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#include <string>
|
||||
void the_function(const std::string& s);
|
||||
|
||||
7
lab1/separate_main.cc
Normal file
7
lab1/separate_main.cc
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#include "separate_fn.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
the_function("Called from main()");
|
||||
exit(0);
|
||||
}
|
||||
56
lab1/test_coding.cc
Normal file
56
lab1/test_coding.cc
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include <iostream>
|
||||
#include "coding.h"
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
std::string do_encode(std::string s)
|
||||
{
|
||||
for(auto& c : s) {
|
||||
c = encode(c);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string do_decode(std::string s)
|
||||
{
|
||||
for(auto& c: s) {
|
||||
c = decode(c);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool test_coding()
|
||||
{
|
||||
std::string str = "Testing, testing... I should be the same after encoding and decoding";
|
||||
|
||||
std::string enc = do_encode(str);
|
||||
assert(enc.size() == str.size()); // sanity check for test program
|
||||
|
||||
bool result = true;
|
||||
for(std::string::size_type i=0; i != enc.size(); ++i){
|
||||
if(enc[i] == str[i]) {
|
||||
std::cout << "enc == str in position " << i << std::endl;
|
||||
result = false;
|
||||
}
|
||||
};
|
||||
|
||||
std::string dec = do_decode(enc);
|
||||
assert(enc.size() == dec.size()); // sanity check for test program
|
||||
|
||||
if(str != dec) {
|
||||
std::cout << "Expected: " << str << "(" << str.size() <<
|
||||
")\nActual: " << dec << "(" << dec.size() << ")" << std::endl;
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if(test_coding()) {
|
||||
std::cout << "Test passed." << std::endl;
|
||||
} else {
|
||||
std::cout << "Test failed." << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
22
lab1/test_editor.cc
Normal file
22
lab1/test_editor.cc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#include "editor.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
void test_equals(Editor::size_type x, Editor::size_type y)
|
||||
{
|
||||
if(x != y) {
|
||||
std::cout << "Wrong result: " << x << " != " << y << std::endl;
|
||||
};
|
||||
}
|
||||
int main() {
|
||||
Editor ed("...(...(...[...]...)...)...{...}...");
|
||||
|
||||
std::cout << "editor.size(): " << ed.get_size() << std::endl;
|
||||
|
||||
test_equals( ed.find_left_par(15), 11);
|
||||
test_equals( ed.find_left_par(19), 7);
|
||||
test_equals( ed.find_left_par(23), 3);
|
||||
test_equals( ed.find_left_par(31), 27);
|
||||
test_equals( ed.find_left_par(32), std::string::npos);
|
||||
std::cout << "test done." << std::endl;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue