OOP Search

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.

Objectives
  • 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)

TimeActivity
0-5Recap through questions
5-15Predict the output of the starting program
15-30Demo: debugger, breakpoints, Locals, Memory
30-60Individual work: find and fix the defects
60-75Extension: a new requirement
75-85Individual checks and short oral questions
85-90Three 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.

L01/L01.cpp

#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.

HintLook at the parameter list of sum. Is sum2 the caller’s variable, or a copy of it?
HintThe 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

  1. What does the compiler tell you?
  2. Don’t fix it yet: why is it wrong?
  3. What value do you predict at this line?
  4. Put a breakpoint here. Was your prediction correct?
  5. 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)

Open in Godbolt

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?

Code in repository: L01

Romanian version