Exercise 12
Added Exercise 12 to Repo
This commit is contained in:
parent
fec3fd845f
commit
99962171df
130
Informatik_I/Exercise_12/Task_1/README.org
Normal file
130
Informatik_I/Exercise_12/Task_1/README.org
Normal file
@ -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
|
46
Informatik_I/Exercise_12/Task_2a/README.org
Normal file
46
Informatik_I/Exercise_12/Task_2a/README.org
Normal file
@ -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 <iostream>
|
||||||
|
|
||||||
|
// 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 🇨🇭
|
51
Informatik_I/Exercise_12/Task_2b/README.org
Normal file
51
Informatik_I/Exercise_12/Task_2b/README.org
Normal file
@ -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 🇨🇭
|
76
Informatik_I/Exercise_12/Task_3/README.org
Normal file
76
Informatik_I/Exercise_12/Task_3/README.org
Normal file
@ -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 <unordered_set>
|
||||||
|
|
||||||
|
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 🇨🇭
|
Loading…
x
Reference in New Issue
Block a user