diff --git a/Informatik_I/Exercise_12/Task_1/README.org b/Informatik_I/Exercise_12/Task_1/README.org new file mode 100644 index 0000000..c58e34b --- /dev/null +++ b/Informatik_I/Exercise_12/Task_1/README.org @@ -0,0 +1,130 @@ +#+TITLE: Task 1: Operator delete +#+AUTHOR: JirR02 + +/This task is a text based task. You do not need to write any program/C++ file: the answer should be written in main.md (and might include code fragments if questions ask for them)./ + +* Task + + All the following code fragments use operator delete and delete[] to deallocate memory, but not appropriately. This can lead to an error (including undefined behaviour) or to a memory leak. Find the mistake in each code fragment, explain whether it results in a memory leak or an error, and in the case of an error, point out the location at which it occurs. + + #+BEGIN_src cpp + class A { + public: + A(int sz) { + ptr = new int[sz]; + } + ~A() { + delete ptr; + } + /* copy constructor, assigmnent operator, public methods. */ + ... + private: + int* ptr; + }; + #+END_src + + #+BEGIN_src cpp + struct lnode { + int value; + lnode* next; + }; + + void recursive_delete_linked_list(lnode* n) { + if (n != nullptr) { + delete n; + recursive_delete_linked_list(n->next); + } + } + #+END_src + + #+BEGIN_src cpp + class A { + public: + A() { + c = new Cell; + c->subcell = new int(0); + } + ~A() { + delete c; + } + /* copy constructor, assignment operator, public methods */ + ... + private: + struct Cell { + int* subcell; + }; + Cell* c; + }; + #+END_src + + #+BEGIN_src cpp + void do_something(int* p) { + /* Do something */ + ... + } + void f() { + int v; + int* w = &v; + do_something(w); + delete w; + } + #+END_src + + #+BEGIN_src cpp + class Vec { + public: + Vec(int size) { + array = new int[size]; + } + ~Vec() { + delete[] array; + } + int& operator[](int idx) { + return array[idx]; + } + /* copy constructor, assignment operator, other public methods */ + ... + private: + int* array; + }; + + void f() { + Vec v(5); + delete[] &v[0]; + } + #+END_src + +* Solution + + #+BEGIN_src md + 1. Mistake: The mistake is that `delete` was used instead of `delete[]` + + Nature: "error (undefined behaviour)" + + Error location (if applicable): The mistake happens when the deconstructor `~A()` is called. + + 2. Mistake: The mistake is that the `lnode` is first deleted and then an attribute of the `lnode` is used, which was already deleted + + Nature: "error" and memory leak" + + Error location (if applicable): The mistake happens in the `if` function when `n` is deleted and recursively recalled. + + 3. Mistake: The mistake is that we only delete `c`without deleting the pointer pointing to the `subcell`. + + Nature: "memory leak" + + Error location (if applicable): The mistake happens when `c` is deleted. + + 4. Mistake: The mistake is that we try to delete an integer from the stack memory. + + Nature: "error (undefined behaviour)" + + Error location (if applicable): The mistake happens when `w` is deleted + + 5. Mistake: The mistake is that `delete` tries to delete the address and not the value allocated tot he memory. + + Nature: "error (undefined behaviour)" + + Error location (if applicable): The mistake happens when `&v[0]` is deleted. + + #+END_src diff --git a/Informatik_I/Exercise_12/Task_2a/README.org b/Informatik_I/Exercise_12/Task_2a/README.org new file mode 100644 index 0000000..8a903ff --- /dev/null +++ b/Informatik_I/Exercise_12/Task_2a/README.org @@ -0,0 +1,46 @@ +#+tilte: Task 2a: Understanding Pointers - Num_Elements +#+author: JirR02 + +* Task Description + + Complete the definition of function =num_elements= by editing the file =num_elements.cpp= according to its specified pre- and post conditions. + + We provide a test program using the implemented function to find the number of elements in a specified interval of a vector. + +** Input + + The test program accepts + + - a vector length, + - the start index a, and + - the end index b. + + For example + + #+BEGIN_src shell + 10 3 10 + #+END_src + + means a 10-element vector and the interval between index 3 and 9. + +** Output + + The test program prints the number of elements in the interval [a,b). + + For example the input given above, this value is 7. + +* Solution + + #+BEGIN_src cpp + #include "num_elements.h" + #include + + // PRE: a <= b are valid pointers to elements of the same contiguous memory + // block. POST: Returns the number of elements in between those pointers + // (starting at a, not including b). + int num_elements(const int *a, const int *b) { return b - a; } + #+END_src + + -------------- + + Made by JirR02 in Switzerland 🇨🇭 diff --git a/Informatik_I/Exercise_12/Task_2b/README.org b/Informatik_I/Exercise_12/Task_2b/README.org new file mode 100644 index 0000000..148750c --- /dev/null +++ b/Informatik_I/Exercise_12/Task_2b/README.org @@ -0,0 +1,51 @@ +#+title: Task 2b: Understanding Pointers - First_Char +#+author: JirR02 + +* Task Description + + Complete the definition of function =first_char= by editing the file =first_char.cpp= according to its specified pre- and post conditions. + + We provide a test program using the implemented function to find the index of the first character in a string. + +** Input + + The program accepts + + * a string s (it may contain whitespaces), followed by a newline, and + * a character c for which to search for the index first occurence + + For example + + #+BEGIN_src shell + jabberwock + b + #+END_src + +** Output + + The pointer to the first element at string =s= where it is equal to character =c=. + + If there is no match, returns a null pointer. + +* Solution + + #+BEGIN_src cpp + #include "first_char.h" + + // PRE: str points within an allocated memory block which contains + // the null character (numerical ASCII value 0) at its last location, + // and nowhere else. + // POST: Returns the pointer to first element at str or after + // that is equal to ch, otherwise return nullptr. + const char *first_char(const char *str, const char ch) { + for (;; str++) + if (*str == ch) + return str; + else if (*str == '\0') + return nullptr; + } + #+END_src + + -------------- + + Made by JirR02 in Switzerland 🇨🇭 diff --git a/Informatik_I/Exercise_12/Task_3/README.org b/Informatik_I/Exercise_12/Task_3/README.org new file mode 100644 index 0000000..ffc5762 --- /dev/null +++ b/Informatik_I/Exercise_12/Task_3/README.org @@ -0,0 +1,76 @@ +#+title: Task 3: Array-based Vector, Rule of Three +#+author: JirR02 + +* Task + + You are provided a partial implementation of an array-based vector class =our_vector=. Declarations are given in file =our_vector.h=, member functions that are already implemented are in file =our_vector_locked.cpp=. Your task is to implement the copy constructor, assignment operator and destructor for class "our_vector", in file =our_vector.cpp=. Note that the vectors store values of type tracked and not =int= as in the lecture, but you can treat them in the same fashion; the tracked values are used behind the scenes for checking your solution. + + *Steps*: + + 1. Implement the copy constructor for class =our_vector= so that it creates a copy of the internal array. + + 1. Implement the assignment operator so that it creates a copy of the provided =our_vector= and destroys the vector that is currently assigned to the left-hand-side of the assignment (e.g., by swapping its current contents to a local copy, as described in the lecture). + + 1. Implement the destructor so that it deallocates the internal array. + + *Memory tracking*: The internal elements of class =our_vector= are objects of class tracked (see file =tracker.h=). Such objects encapsulate a single integer location which is tracked by an internal memory manager. This is used internally to catch as many memory/deallocation errors as possible upon occurrence. + + *Testing*: Tests are already provided in file =main.cpp=. If you want to carry out further testing yourself, you may do so within function =your_own_tests()=, which is called by =main()= when encountering an unknown test identifier. You can edit this function in file =our_vector.cpp=. + + *Valgrind output* After you implemented the copy constructor (subtask 1), you may see the following (or similar) output generated by valgrind: + + #+BEGIN_src shell + Remaining tracked elements: 6 + + memory errors: + [ERROR:Leak_DefinitelyLost] 20 bytes in 1 blocks are definitely lost in loss record 1 of 2 + in function `our_vector::our_vector(int)` at our_vector_locked.cpp:6 + in function `test_copy_constructor()` at main.cpp:9 + in function `main` at main.cpp:63 + [ERROR:Leak_DefinitelyLost] 20 bytes in 1 blocks are definitely lost in loss record 2 of 2 + in function `our_vector::our_vector(our_vector const&)` at our_vector.cpp:5 + in function `test_copy_constructor()` at main.cpp:13 + in function `main` at main.cpp:63 + #+END_src + + This indicates that in your program some memory has been dynamically allocated (in this case one =our_vector= object), but then this memory is definitely /lost/ when the main function returns (the memory can not be longer accessed). + + To solve this issue, you have to implement the object destructor (subtask 3). + +* Solution + + #+BEGIN_src cpp + #include "our_vector.h" + #include + + our_vector::our_vector(const our_vector &vec) /* TODO */ { + count = vec.count; + elements = new tracked[count]; + for (int i = 0; i < count; ++i) { + elements[i] = vec.elements[i]; + } + } + + our_vector &our_vector::operator=(const our_vector &t) { + if (this != &t) { + delete[] elements; + + count = t.count; + elements = new tracked[count]; + + for (int i = 0; i < count; ++i) + elements[i] = t.elements[i]; + } + return (*this); + } + + our_vector::~our_vector() { delete[] elements; } + + void your_own_tests() { + // Any extra test here. + } + #+END_src + + -------------- + + Made by JirR02 in Switzerland 🇨🇭