Managing and Debugging C++ Programs
COSC1076 Week 04
Pointers & References
Copyright By PowCoder代写 加微信 powcoder
The most important topic in the course!
Computer Memory
Each byte has a unique address
• This is how a computer can find a piece of memory
• Addresses are stored in hex, and adjacent memory locations are sequential
Pointer Name Memory
character:
0x0004fca4
0x0004fca8
0x0004fca9
Week 04 | Managing and Debugging C++ Programs COSC1076
Pointers & References
A reference type is denoted in syntax using a ‘&’
int value = 7;
int* ptr = &value;
int& ref = value;
ptr = NULL;
int* ptr int value int& ref
Week 04 | Managing and Debugging C++ Programs COSC1076
Arrays as Pointers
An array is actually an abstraction for using pointers!
The actual array “variable” is a pointer to the first element of the array
The square-bracket lookup notation is short-hand for: • Go to the memory location of the array
• Go to the ‘ith’ memory location from this
• Dereference that memory address
Week 04 | Managing and Debugging C++ Programs COSC1076
Arrays as Pointers
In C/C++, a pointer type is another way to represent an array
int array[10]
int* array;
• The first version actually set’s aside the memory for the array
• The second can be interpreted as an array, but only sets aside memory for a single pointer
The “pointer form” of an array is often used in functions and methods
Week 04 | Managing and Debugging C++ Programs COSC1076
Multi-Dimensional Arrays
The best way to think of them, is as an “array-of-arrays” • At the first layer, is an array
• Each element of this is another array
int** array2D; array2D:
Week 04 | Managing and Debugging C++ Programs COSC1076
Review: Classes
Classes Declaration
class Example {
Class Name
Example(int value);
Constructor Method
~Example();
Public, Protected, & Private Scopes
void publicMethod(); protected:
Deconstructor Field
int protectedVariable;
int protectedMethod(double param);
Fields can be arrays or other classes
double privateArray[LENGTH];
void privateMethod(int* ptr, double& ref);
Don’t forget ‘;’
Week 04 | Managing and Debugging C++ Programs COSC1076
“this” Pointer
Like in Java, C++ Classes have a special keyword this
• It gives a pointer to the current object of the class
• Using the keyword, all methods and fields of the class can be accessed • Works in constructors and methods
Example::Example(int value) {
this->protectedVariable = value;
int Example::protectedMethod(double param) {
this->protectedVariable = param;
Week 04 | Managing and Debugging C++ Programs COSC1076
Classes – allocating
Allocating memory for a Class creates an object of that class Example* ex = new Example(10);
Creating an object calls a constructor of the class
• A constructor must always be called
• Even if that constructor is empty (takes no parameters)
Example* ex = new Example();
• If a class defines no constructors, C++ will generate a default empty constructor
Week 04 | Managing and Debugging C++ Programs COSC1076
Classes – deallocating
When an object is deleted, a special method is called • This method is the deconstructor
– The deconstructor is denoted with a tilde (~) – It always takes no parameters
class Example {
Example(int value);
Example* ex(10);
delete ex;
~Example();
Implementation
Calls deconstructor
Example::~Example() {
// cleanup
Week 04 | Managing and Debugging C++ Programs COSC1076
Program Memory Management
Program/Call Stack
A stack is used, because of how memory is allocated
Highest address
Lowest address
Bottom of stack (main)
Variables (function 2)
Return address (function 2)
Memory allocation has two components
1. Variable allocation 2. Function call
Parameters (function 2)
Return Value (function 2)
Variables (function 1)
Return address (function 1)
Parameters (function 1)
Return Value (function 1)
Variables (of main)
Week 04 | Managing and Debugging C++ Programs COSC1076
Heap (Free Store)
The programmer manages the allocation and de-allocation of memory on the
In Java, objects are allocated on the heap
Object obj = new Object();
• The “new” keyword creates the object • The object is stored on the heap
Week 04 | Managing and Debugging C++ Programs COSC1076
Heap – De-allocation
Any memory that is allocated, should be de-allocated
• Also called “freeing” or “deleting” memory
• By de-allocating memory, a program can re-use it for another purpose
• If memory is not “cleaned-up”, the Operating System is not aware that memory is no longer needed
– Any new memory that a program requires, must be allocated elsewhere
Java has automated garbage collection, so the programmer does not have to be concerned with de-allocating the memory
• In C++, You (the programmer) MUST de-allocate all memory
Only when a program is terminated, will the operating system reclaim all memory that was not de-allocated
Week 04 | Managing and Debugging C++ Programs COSC1076
Multi-File Programs
Header Files
Header files contain definitions, such as • Function prototypes
• Class descriptions
• Typedef’s
• Common #define’s
Header files do not contain any code implementation
The purpose of the header files is to describe to source files all of the information that is required in order to implement some part of the code
Week 04 | Managing and Debugging C++ Programs COSC1076
Source Files
Code files have source code definitions / implementations
• In a single combined program, every function or class method may only have a single implementation
To successfully provide implementations, the code must be given all necessary declarations to fully describe all types and classes that are being used
• Definitions in header files are included in the code file
#include “header.h” – For local header files, use double-quotes
– Use relative-path to the header file from the code file
Week 04 | Managing and Debugging C++ Programs COSC1076
Multiple Includes
What happens if a header file in included multiple times? • Can create naming errors re-declaration errors.
Two solutions
1. Be careful about what files are included, but this quickly becomes infeasible with long include chains
2. Use pre-processor commands
Week 04 | Managing and Debugging C++ Programs COSC1076
#ifdef / #ifndef / #endif
The pre-processor can be used to see if a name as been #define’d • #ifdef – check if a definition exists
• #ifndef – check if a definition does not exist
• #endif – Close a #if check
Any code between a #if check will only be included if the check passes • If the check does not pass, the code is essentially ignored
Typical pattern for a header file:
/* Header file implementation */ #endif // TERM_FOR_HEADER_FILE
#ifndef TERM_FOR_HEADER_FILE
#define TERM_FOR_HEADER_FILE
Week 04 | Managing and Debugging C++ Programs COSC1076
More on Classes & Pointers
Default Constructor
A Default Constructor is a special constructor that takes no parameters • It sets all fields of the class to default values
• These values don’t have to be “zero”, but should be sensible defaults
Typically C++ programs presume all classes have a default constructor
• This might not always make sense depending on the design of the program.
• Thus a default constructor is not always required, however, this may cause compilations issues with the C++ STL if you are not careful.
Week 04 | Managing and Debugging C++ Programs COSC1076
Copy Constructors
A Copy Constructor is a special constructor that duplicates an existing object • It must take a reference to an existing object of the same type
• It makes an identical copy of the existing object
What does “copy” mean?
• Two general forms
• Shallow copy – only the immediate fields are duplicated, not the contents of any sub-classes
• Deep copy – duplicate all contents of every field
Week 04 | Managing and Debugging C++ Programs COSC1076
Constructors
class Card {
Default Constructor
Constructor
Copy Constructor Deconstructor
Card(std::string& name);
Card(Card& other);
std::string colour; int number;
Week 04 | Managing and Debugging C++ Programs COSC1076
Initialising Fields
Fields must be initialised in a constructor.
C++ Provides a useful syntax shorthand to initialise fields • Uses colon (:) syntax
Card::Card(std::string& colour, int number) :
colour(colour),
number(number)
Card::Card(Card& other) :
colour(other.colour),
number(other.number)
Week 04 | Managing and Debugging C++ Programs COSC1076
More Language Features
Enumeration
An enumeration creates a new type that has a fixed set of values • These values are named
• Only these values may be used
Enumeration provides compile time guarantees about the set of permitted types
enum Colour {
int main(void) {
Colour colour = RED;
Week 04 | Managing and Debugging C++ Programs COSC1076
Software Problem Solving
C.A.R. Hoare on Software Design
“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”
— Sir Charles Hoare.
Week 04 | Managing and Debugging C++ Programs COSC1076
Problem Solving
Problem Solving is about find software solutions to problems • It’s an obvious statement, but what does it actually mean?
Software Design
Implementation
Week 04 | Managing and Debugging C++ Programs COSC1076
Problem Solving
Problem Solving != Debugging.
Problem Solving != ad-hoc compile-and-tweak.
There are usually many possible solutions to a problem.
The design of algorithms and software are hardest parts of the problem solving process.
• Actual implementation is often simple
A designers three most important tools are • Knowledge
• Experience
• Good judgement
Week 04 | Managing and Debugging C++ Programs COSC1076
Object Ownership
Object Ownership
Ownership is the concept of who (which module/object/code) has responsibility for managing the life-cycle of memory allocated on the heap
• That is, who controls a piece of programmer-managed memory*
Aspects of ownership include:
• Who controls which other code can modify a piece of memory
• Who must de-allocate (delete) memory when it is no longer required
*For the purposes of this discussion, memory allocated on the heap will be referred to as “objects”. However this may include:
• Primitive Types
• Objects of Classes
Week 04 | Managing and Debugging C++ Programs COSC1076
Managing Owned Objects
The owner of programmer-allocated objects must consider include: • How is an object allocated?
• What values can be read?
• What values can be modified?
• Who can read or modify values?
• When can values be read or modified?
• Is it clear that the code manages the life-cycle of the object? • When should the object be de-allocated?
Week 04 | Managing and Debugging C++ Programs COSC1076
Accessing Non-Owned Objects
A user of a non-owned programmer-allocated object must consider: • Is the object allocated and available to use?
• Am I permitted to access, read and/or modify the object?
• How should I read access or modify the object?
• Can the object be modified by someone else?
• What happens is someone else modified the object?
• When does the object get de-allocated?
• Am I aware of when or if an object is de-allocated?
• Is it possible for me to access an object after it has been de-allocated?
Week 04 | Managing and Debugging C++ Programs COSC1076
Transferring Ownership of Objects
Ownership over an object may be transferred
• The previous owner is no longer responsible for managing the object • The new owner assume management responsibility
Third-party users of the object (code that is not involved in the transfer) should be aware of the transfer of ownership
Transferring ownership can be fraught with danger:
• It must be clear that ownership is transferred
• Failing to correctly transfer ownership leaks to memory leaks and segmentation faults
Week 04 | Managing and Debugging C++ Programs COSC1076
Self-Managed Objects
A fully self-managed object internally decides: • Who may access and modify its contents
• When to delete itself
Generally, when using a self managed object, it must be assumed that • Other code can access and modify the object
• “You” have no control over when the object is destroyed
Generally, a self-managed object will internally track references to itself’s, and automatically detect when there are no references to it.
• Then it will delete itself
By default, Java uses self-managed objects
• We will discuss implementing self-managed objects later in the course
Week 04 | Managing and Debugging C++ Programs COSC1076
Partial Compilation
Executable Generation
A full C++ program that can be run is termed executable
The full C++ build process* takes written code and converts it into an
executable
So far, we take all code and build it together, but during the development cycle this is inefficient for developers.
• Often, only a small portion of the code is modified • Full rebuilds can be slow and are unnecessary
* Most programming languages follow a similar process to varying degrees. Thus, this discussion is not specific to C++!
Week 04 | Managing and Debugging C++ Programs COSC1076
Development Cycle
Week 04 | Managing and Debugging C++ Programs COSC1076
Partial Compilation
Partial compilation:
• Compiles a subset of a codebase
• Compiles the subset to as close to an executable format as possible without the “missing” code
• Does not need to be rebuilt unless the originating subset of the code is modified
Full compilation takes the partially compiled code and produces an executable
Week 04 | Managing and Debugging C++ Programs COSC1076
C/C++ Compilation Process
C++ Source File (.cpp)
Pre-processor
File (.s) Object File (.o) Executable
Week 04 | Managing and Debugging C++ Programs
Preprocessor
The pre-processor first runs and evaluates all ‘#’ statements • #include – import header file
• #define – define a new constant
• #ifdef – check if a definition exists
• #ifndef – check if a definition does not exist
• #endif – Close a #if check
This generates a temporary C++ code file that is given to the compiler
The pre-processor is compiler dependent
• Not all compilers support all ‘#’ statements
• There are very few ‘#’ statements included in the C++14 language
Week 04 | Managing and Debugging C++ Programs COSC1076
#ifdef / #ifndef / #endif
The pre-processor can be used to see if a name as been #define’d • #ifdef – check if a definition exists
• #ifndef – check if a definition does not exist
• #endif – Close a #if check
Any code between a #if check will only be included if the check passes • If the check does not pass, the code is essentially ignored
Typical pattern for a header file:
/* Header file implementation */ #endif // TERM_FOR_HEADER_FILE
#ifndef TERM_FOR_HEADER_FILE
#define TERM_FOR_HEADER_FILE
Week 04 | Managing and Debugging C++ Programs COSC1076
C++ Partial Compilation (Object Files)
An individual code file (cpp file) can be partially compiled into an object file
An object file is
• Machine code (1’s and 0’s)
• Is missing “links” to variables, functions, and methods that the code file calls and depends on for it to actually run
• Contains a symbol table for all of these “missing links”
• The symbols denote what the code depends upon
Week 04 | Managing and Debugging C++ Programs COSC1076
C++ Partial Compilation (Object Files)
Object files made with g++, with the -c flag • The -o flag is optional
g++ … —c
Object files are then compiled together just like compiling multiple code files
g++ … —o
• The -o flag is required
Week 04 | Managing and Debugging C++ Programs COSC1076
C++ Partial Compilation (Linker)
The linker connects all of the “missing links” between the object files
• This is done by matching up the symbols in each of the symbol tables of the
object files
• The symbols must exactly match for linking to occur
After linking, objects files become a full executable
Week 04 | Managing and Debugging C++ Programs COSC1076
Libraries are code that have been developed by other and is shared
So the question is:
• Should code in libraries be compiled anew by every developer who uses the library?
• Should libraries be pre-compiled?
If a library is rebuilt:
• Requires more time for the developer using the library • Easier to share
• We’ve seen this with:
– iostream – std::string – cstdio
Week 04 | Managing and Debugging C++ Programs COSC1076
Pre-compiled Libraries
If a library is pre-compiled:
• Must be pre-compiled for every different CPU architecture
• Saves time for developers rebuilding the library, which can be significant for large libraries
• The library developers have more control over compilation, which may be especially significant for optimisation of the code
In C++, libraries must link against the pre-compiled library • Uses the “linker” flag
-l
Week 04 | Managing and Debugging C++ Programs COSC1076
Executable Generation Pitfalls
Partial compilation can lead to runtime errors
• The most common mistake is that code is not rebuilt!
• In large projects, or where libraries are used, conflicts may occur is different subsets of the codebase are compiled against different versions of the project, or against different versions of libraries.
If in doubt, re-compile from scratch
Java 1.4 (which introduced generics) actually had a major problem that could occur through partial compilation which let to run-time errors!
Week 04 | Managing and Debugging C++ Programs COSC1076
Automated Build
make is a tool for automated compilation that dates back to 1976
Make is a simple tool to for automated build
• It is language independent, though typically used for C/C++ • Make specified automated build through a series of rules.
• A rule contains:
– A target
– Dependencies – A command
Week 04 | Managing and Debugging C++ Programs COSC1076
Make rules are always placed in a file called ‘Makefile’
• A rule of a makefile are executed using the “make” utility/command
make
• If no target is given, the “default” target is run
Week 04 | Managing and Debugging C++ Programs COSC1076
Default Rule
Target Name
Dependencies
.default: all
unit_tests
rm -f unit_tests *.o
unit_tests: Particle.o ParticleList.o ParticleFilter.o
unit_tests.o
Compilation Command
g++ -Wall -Werror -std=c++14 -O -o $@ $^
%.o: %.cpp
Pattern Rule
g++ -Wall -Werror -std=c++14 -O -c $^
Week 04 | Managing and Debugging C++ Programs COSC1076
Beyond Make
Make is a simple but effective tool
• However, for complex projects it quickly becomes annoying to manually write makefiles
• Additional automated build tools provide layers of abstract to further automate different aspects of building programs
• Interestingly, many of these tools eventually generate and use
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com