Week 01 / 14 Object-Oriented Programming
Lab 1 - Debugger and the memory model
We start from a program with defects. We read it, predict what it does, step through it in the debugger, and fix it.
- Create, build and run a C++ project
- Tell compilation, linking, logical and runtime problems apart
- Use breakpoints and step through code
- Inspect variables and reason about the stack
- Explain value, address, pointer and reference
- Predict simple program behaviour before running it
Plan (90 min)
| Time | Activity |
|---|---|
| 0-5 | Recap through questions |
| 5-15 | Predict the output of the starting program |
| 15-30 | Demo: debugger, breakpoints, Locals, Memory |
| 30-60 | Individual work: find and fix the defects |
| 60-75 | Extension: a new requirement |
| 75-85 | Individual checks and short oral questions |
| 85-90 | Three things you know now |
Starting program
The code is in the repository, in the L01 folder. Don’t run it yet. Read it and write down what you think it prints.
#include <stdio.h>
#include <iostream>
using namespace std;
void sum(int a, int b, int sum2) /// passing by value
{
sum2 = a + b;
a = 0; b = 0;
}
//printf("%d", a + b);
void sumRef(int a, int b, int &sum2) /// passing by reference (C++ ONLY)
{
sum2 = a + b;
a = 0; b = 0;
}
void sumAdress(int* a, int* b, int* sum2) /// passing by Adress
{
*sum2 = *a + *b;
*a = 0; *b = 0;
}
void main()
{
int a, b, sum2;
sum2 = 0;
printf("a = "); scanf_s("%d", &a);
printf("b = "); scanf_s("%d", &b);
sumAdress(&a, &b, &sum2);
cout << "a= " << a;
cout << "b = " << b;
printf("sum 2=");
printf("%d", sum2);
}
Find the defects
The sum function
sum should store a + b in the caller’s sum2. After calling it, main still sees the old value. Why? Compare it with sumRef and sumAdress.
Put a breakpoint on the first line of sum. In the Locals window, compare the address of sum2 inside sum (&sum2) with its address in main.
Hint
Look at the parameter list ofsum. Is sum2 the caller’s variable, or a copy of it?Hint
The two addresses are different:sum writes into its own copy, which disappears when the function returns.Solution
void sum(int a, int b, int& sum2) { // take sum2 by reference
sum2 = a + b;
}Passing by value copies the argument. To change the caller’s variable, pass it by reference (int&) or by address (int*, then write through *sum2).
Mandatory questions
- What does the compiler tell you?
- Don’t fix it yet: why is it wrong?
- What value do you predict at this line?
- Put a breakpoint here. Was your prediction correct?
- What is on the stack at this point?
Predict, then check:
#include <iostream>
using namespace std;
void sumAdress(int* a, int* b, int* sum2) { *sum2 = *a + *b; *a = 0; *b = 0; }
int main() {
int a = 2, b = 3, sum2 = 0;
sumAdress(&a, &b, &sum2);
cout << a << " " << b << " " << sum2;
} #include <iostream>
using namespace std;
void sum(int a, int b, int sum2) { sum2 = a + b; a = 0; b = 0; }
int main() {
int a = 2, b = 3, sum2 = 0;
sum(a, b, sum2);
cout << a << " " << b << " " << sum2;
} Minimum task
Average of an array
Fix sum, then add double average(double* values, int n), which returns the average of the n values. Test it with at least two data sets, one of them with n = 1.
#include <iostream>
using namespace std;
double average(double* values, int n) {
// TODO: compute the average
return 0;
}
int main() {
double grades[] = {7, 9, 10, 6};
cout << average(grades, 4) << endl; // expected: 8
}Input (stdin)
Requirement change
New requirement: write void minMax(double* values, int n, double& mn, double& mx), which returns the minimum and the maximum through references. Why can’t you return two values with return? What other options do you have?