|
7 | 7 | \begin{cppcode*}{xleftmargin=20pt}
|
8 | 8 | char *s;
|
9 | 9 | try {
|
10 |
| - callThatThrows(); |
11 |
| - s = (char*) malloc(...); |
12 |
| - strncpy(s, ...); |
| 10 | + foo(); // may throw |
| 11 | + s = new char[100]; |
| 12 | + read_line(s); |
13 | 13 | } catch (...) { ... }
|
14 |
| - bar(s); |
| 14 | + process_line(s); |
15 | 15 | \end{cppcode*}
|
16 | 16 | \end{exampleblock}
|
17 | 17 | \pause
|
|
20 | 20 | \begin{exampleblock}{They need to be released
|
21 | 21 | \hfill \onslide<4->{\textcolor{orange}{\bf Memory leak}}}
|
22 | 22 | \begin{cppcode*}{xleftmargin=20pt}
|
23 |
| - char *s = (char*) malloc(...); |
24 |
| - strncpy(s, ...); |
25 |
| - if (0 != strncmp(s, ...)) return; |
26 |
| - foo(s); |
27 |
| - free(s); |
| 23 | + char *s = new char[100]; |
| 24 | + read_line(s); |
| 25 | + if (s[0] == '#') return; |
| 26 | + process_line(s); |
| 27 | + delete[] s; |
28 | 28 | \end{cppcode*}
|
29 | 29 | \end{exampleblock}
|
30 | 30 | \pause
|
|
33 | 33 | \begin{exampleblock}{They need clear ownership
|
34 | 34 | \hfill \onslide<6->{\textcolor{orange}{\bf Who should release ?}}}
|
35 | 35 | \begin{cppcode*}{xleftmargin=20pt}
|
36 |
| - char *s = (char*) malloc(...); |
37 |
| - strncpy(s, ...); |
38 |
| - someVector.push_back(s); |
39 |
| - someSet.add(s); |
40 |
| - std::thread t1(vecConsumer, someVector); |
41 |
| - std::thread t2(setConsumer, someSet); |
| 36 | + char *s = new char[100]; |
| 37 | + read_line(s); |
| 38 | + vec.push_back(s); |
| 39 | + set.add(s); |
| 40 | + std::thread t1(func1, vec); |
| 41 | + std::thread t2(func2, set); |
42 | 42 | \end{cppcode*}
|
43 | 43 | \end{exampleblock}
|
44 | 44 | \end{frame}
|
|
47 | 47 | \frametitlecpp[11]{This problem exists for any resource}
|
48 | 48 | \begin{exampleblock}{For example with a file}
|
49 | 49 | \begin{cppcode*}{}
|
50 |
| - try { |
51 |
| - FILE *handle = std::fopen(path, "w+"); |
52 |
| - if (nullptr == handle) { throw ... } |
53 |
| - if (std::fputs(str, handle) == EOF) { |
54 |
| - throw ... |
55 |
| - } |
56 |
| - fclose(handle); |
57 |
| - } catch (...) { ... } |
| 50 | + std::FILE *handle = std::fopen(path, "w+"); |
| 51 | + if (nullptr == handle) { throw ... } |
| 52 | + std::vector v(100, 42); |
| 53 | + write(handle, v); |
| 54 | + if (std::fputs("end", handle) == EOF) { |
| 55 | + return; |
| 56 | + } |
| 57 | + std::fclose(handle); |
58 | 58 | \end{cppcode*}
|
59 | 59 | \end{exampleblock}
|
| 60 | + \begin{block}{} |
| 61 | + Which problems do you spot in the above snippet? |
| 62 | + \end{block} |
60 | 63 | \end{frame}
|
61 | 64 |
|
62 | 65 | \begin{frame}
|
|
80 | 83 | class File {
|
81 | 84 | public:
|
82 | 85 | File(const char* filename) :
|
83 |
| - m_file_handle(std::fopen(filename, "w+")) { |
84 |
| - if (m_file_handle == NULL) { throw ... } |
| 86 | + m_handle(std::fopen(filename, "w+")) { |
| 87 | + if (m_handle == nullptr) { throw ... } |
85 | 88 | }
|
86 |
| - ~File() { std::fclose(m_file_handle); } |
| 89 | + ~File() { std::fclose(m_handle); } |
87 | 90 | void write (const char* str) {
|
88 |
| - if (std::fputs(str, m_file_handle) == EOF) { |
| 91 | + if (std::fputs(str, m_handle) == EOF) { |
89 | 92 | throw ...
|
90 | 93 | }
|
91 | 94 | }
|
92 | 95 | private:
|
93 |
| - FILE* m_file_handle; |
| 96 | + std::FILE* m_handle; |
94 | 97 | };
|
95 | 98 | \end{cppcode*}
|
96 | 99 | \end{exampleblock}
|
|
113 | 116 | \end{cppcode*}
|
114 | 117 | \end{exampleblock}
|
115 | 118 | \begin{alertblock}{}
|
116 |
| - \begin{itemize} |
117 |
| - \item on real projects, use \mintinline{cpp}{std::fstream} to handle files |
118 |
| - \end{itemize} |
| 119 | + The standard library provides \mintinline{cpp}{std::fstream} to handle files, use it! |
119 | 120 | \end{alertblock}
|
120 | 121 | \end{frame}
|
121 | 122 |
|
|
200 | 201 | \frametitlecpp[11]{RAII or raw pointers}
|
201 | 202 | \begin{block}{When to use what ?}
|
202 | 203 | \begin{itemize}
|
203 |
| - \item Always use RAII for all resources, in particular allocations |
| 204 | + \item Always use RAII for resources, in particular allocations |
204 | 205 | \item You thus never have to release / deallocate yourself
|
205 | 206 | \item Use raw pointers as non-owning, re-bindable observers
|
206 | 207 | \item Remember that \mintinline{cpp}{unique_ptr} is move only
|
|
0 commit comments