@@ -7,10 +7,10 @@ Please answer the following questions and submit in your repo for the second ass
> **Answer**: Yes, externalizing `get_student()` improves the design because:
>
> 1. It avoids duplicating file access code across multiple operations (finding, deleting, adding students)
> 2. It separates the low-level file access details from higher-level database operations
> 3. Changes to how students are read only need to be made in one place
> 4. The isolated function is easier to test
> - It avoids duplicating file access code across multiple operations (finding, deleting, adding students)
> - It separates the low-level file access details from higher-level database operations
> - Changes to how students are read only need to be made in one place
> - The isolated function is easier to test
2. Another interesting aspect of the `get_student(...)` function is how its function prototype requires the caller to provide the storage for the `student_t` structure:
...
...
@@ -44,7 +44,7 @@ Please answer the following questions and submit in your repo for the second ass
```
Can you think of any reason why the above implementation would be a **very bad idea** using the C programming language? Specifically, address why the above code introduces a subtle bug that could be hard to identify at runtime?
> **Answer**: This implementation is dangerous because it returns a pointer to a local variable (`student`) that is destroyed when the function returns. Using this pointer would cause undefined behavior since it points to invalid memory. This is a common source of bugs in C programs since the memory corruption may not be immediately apparent.
> **Answer**: This implementation is dangerous because it returns a pointer to a local variable `student` that is destroyed when the function returns. Using this pointer would cause undefined behavior since it points to invalid memory.
3. Another way the `get_student(...)` function could be implemented is as follows:
...
...
@@ -79,10 +79,10 @@ Please answer the following questions and submit in your repo for the second ass
> **Answer**: While this implementation would work, it has important drawbacks:
>
> 1. It requires callers to remember to free the memory, risking memory leaks
> 2. NULL return is ambiguous - could mean "not found" or "allocation failed"
> 3. Unnecessarily allocates memory when passing existing memory would work
> 4. Different callers might manage the memory inconsistently
> - It requires callers to remember to free the memory, risking memory leaks
> - NULL return is ambiguous - could mean "not found" or "allocation failed"
> - Unnecessarily allocates memory when passing existing memory would work
> - Different callers might manage the memory inconsistently
4. Lets take a look at how storage is managed for our simple database. Recall that all student records are stored on disk using the layout of the `student_t` structure (which has a size of 64 bytes). Lets start with a fresh database by deleting the `student.db` file using the command `rm ./student.db`. Now that we have an empty database lets add a few students and see what is happening under the covers. Consider the following sequence of commands: