# HG changeset patch # User František Kučera # Date 1730252684 -3600 # Node ID e4f2d6d0e869fceef7d2426fb3e6a43d333b6467 blok finally v C++ diff -r 000000000000 -r e4f2d6d0e869 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Wed Oct 30 02:44:44 2024 +0100 @@ -0,0 +1,28 @@ +CXX ?= g++ +CXXFLAGS ?= -O2 -g3 -ggdb -Wall -Wno-sign-compare +CXXFLAGS += --std=c++20 +CXXFLAGS += -fsanitize=undefined -fsanitize=address +LDFLAGS ?= + +SRC = $(shell find -maxdepth 1 -name '*.cpp') +BIN = $(shell find -maxdepth 1 -name '*.cpp' | xargs basename -s .cpp) + +all: $(BIN) + +.PHONY: all run clean + +clean: + $(RM) $(BIN) + +run: $(BIN) + @echo "\e[1;32mHappy path without exceptions:\e[0m" + @for bin in $(BIN); do ./$$bin ; done + @echo; echo + @echo "\e[1;32mInterrupted by exceptions:\e[0m" + @for bin in $(BIN); do ./$$bin fail; done + +$(BIN): $(SRC) + $(CXX) $(CXXFLAGS) -o $(@) $(@).cpp $(LDFLAGS) + +# Blok finally při odchytávání výjimek: C++ vs. Java +# https://blog.frantovo.cz/c/395/ diff -r 000000000000 -r e4f2d6d0e869 bad.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bad.cpp Wed Oct 30 02:44:44 2024 +0100 @@ -0,0 +1,26 @@ +#include +#include + +void fxThrowing(bool fail, void* data) { + std::cout << " doing something with data " << data << std::endl; + if (fail) throw std::logic_error("error from fxThrowing()"); +} + +void fxAllocating(bool fail) { + void* data = malloc(486); + std::cout << " allocated memory at: " << data << std::endl; + fxThrowing(fail, data); + free(data); + std::cout << " freed memory at: " << data << std::endl; +} + +int main(int argc, char** argv) { + bool fail = argc == 2 && std::string("fail") == argv[1]; + const char* name = "bad"; + std::cout << name << " (fail=" << fail << ")\n"; + try { + fxAllocating(fail); + } catch (const std::exception& e) { + std::cout << " caught exception: " << e.what() << std::endl; + } +} \ No newline at end of file diff -r 000000000000 -r e4f2d6d0e869 good-class-generic.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/good-class-generic.cpp Wed Oct 30 02:44:44 2024 +0100 @@ -0,0 +1,42 @@ +#include +#include + +template +class Resource { +private: + Resource(const Resource&) = delete; + Resource& operator=(const Resource&) = delete; +public: + T* data; + void(*dtor)(T*); + + Resource(T* data, void(*dtor)(T*)) : data(data), dtor(dtor) { + std::cout << " created resource for data at: " << data << std::endl; + } + + virtual ~Resource() { + dtor(data); + std::cout << " called destructor on: " << data << std::endl; + } +}; + +void fxThrowing(bool fail, void* data) { + std::cout << " doing something with data " << data << std::endl; + if (fail) throw std::logic_error("error from fxThrowing()"); +} + +void fxAllocating(bool fail) { + Resource buf(malloc(486), free); + fxThrowing(fail, buf.data); +} + +int main(int argc, char** argv) { + bool fail = argc == 2 && std::string("fail") == argv[1]; + const char* name = "good-class-generic"; + std::cout << name << " (fail=" << fail << ")\n"; + try { + fxAllocating(fail); + } catch (const std::exception& e) { + std::cout << " caught exception: " << e.what() << std::endl; + } +} diff -r 000000000000 -r e4f2d6d0e869 good-class.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/good-class.cpp Wed Oct 30 02:44:44 2024 +0100 @@ -0,0 +1,41 @@ +#include +#include + +class Buffer { +private: + Buffer(const Buffer&) = delete; + Buffer& operator=(const Buffer&) = delete; +public: + size_t size; + void* data; + + Buffer(size_t size) : size(size), data(malloc(size)) { + std::cout << " allocated memory at: " << data << std::endl; + } + + virtual ~Buffer() { + free(data); + std::cout << " freed memory at: " << data << std::endl; + } +}; + +void fxThrowing(bool fail, void* data) { + std::cout << " doing something with data " << data << std::endl; + if (fail) throw std::logic_error("error from fxThrowing()"); +} + +void fxAllocating(bool fail) { + Buffer buf(486); + fxThrowing(fail, buf.data); +} + +int main(int argc, char** argv) { + bool fail = argc == 2 && std::string("fail") == argv[1]; + const char* name = "good-class"; + std::cout << name << " (fail=" << fail << ")\n"; + try { + fxAllocating(fail); + } catch (const std::exception& e) { + std::cout << " caught exception: " << e.what() << std::endl; + } +} diff -r 000000000000 -r e4f2d6d0e869 good-finally.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/good-finally.cpp Wed Oct 30 02:44:44 2024 +0100 @@ -0,0 +1,36 @@ +#include +#include + +void fxThrowing(bool fail, void* data) { + std::cout << " doing something with data " << data << std::endl; + if (fail) throw std::logic_error("error from fxThrowing()"); +} + +void fxAllocating(bool fail) { + void* data = malloc(486); + std::cout << " allocated memory at: " << data << std::endl; + + std::exception_ptr e; + try { + fxThrowing(fail, data); + } catch (...) { + e = std::current_exception(); + } + + // finally: + free(data); + std::cout << " freed memory at: " << data << std::endl; + + if (e) std::rethrow_exception(e); +} + +int main(int argc, char** argv) { + bool fail = argc == 2 && std::string("fail") == argv[1]; + const char* name = "good-finally"; + std::cout << name << " (fail=" << fail << ")\n"; + try { + fxAllocating(fail); + } catch (const std::exception& e) { + std::cout << " caught exception: " << e.what() << std::endl; + } +} \ No newline at end of file diff -r 000000000000 -r e4f2d6d0e869 good-smart-pointer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/good-smart-pointer.cpp Wed Oct 30 02:44:44 2024 +0100 @@ -0,0 +1,38 @@ +#include +#include +#include + +/** not needed, just for logging */ +void* myMalloc(size_t size) { + void* ptr = ::malloc(size); + std::cout << " allocated memory at: " << ptr << std::endl; + return ptr; +} + +/** not needed, just for logging */ +void myFree(void* ptr) { + ::free(ptr); + std::cout << " freed memory at: " << ptr << std::endl; +} + +void fxThrowing(bool fail, void* data) { + std::cout << " doing something with data " << data << std::endl; + if (fail) throw std::logic_error("error from fxThrowing()"); +} + +void fxAllocating(bool fail) { + // std::shared_ptr buf(malloc(486), free); // standard functions + std::shared_ptr buf(myMalloc(486), myFree); // our ones with logging + fxThrowing(fail, buf.get()); +} + +int main(int argc, char** argv) { + bool fail = argc == 2 && std::string("fail") == argv[1]; + const char* name = "good-smart-pointer"; + std::cout << name << " (fail=" << fail << ")\n"; + try { + fxAllocating(fail); + } catch (const std::exception& e) { + std::cout << " caught exception: " << e.what() << std::endl; + } +} diff -r 000000000000 -r e4f2d6d0e869 good-vector.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/good-vector.cpp Wed Oct 30 02:44:44 2024 +0100 @@ -0,0 +1,24 @@ +#include +#include +#include + +void fxThrowing(bool fail, void* data) { + std::cout << " doing something with data " << data << std::endl; + if (fail) throw std::logic_error("error from fxThrowing()"); +} + +void fxAllocating(bool fail) { + std::vector buf(486); + fxThrowing(fail, buf.data()); +} + +int main(int argc, char** argv) { + bool fail = argc == 2 && std::string("fail") == argv[1]; + const char* name = "good-vector"; + std::cout << name << " (fail=" << fail << ")\n"; + try { + fxAllocating(fail); + } catch (const std::exception& e) { + std::cout << " caught exception: " << e.what() << std::endl; + } +}