SlideShare ist ein Scribd-Unternehmen logo
1 von 29
Downloaden Sie, um offline zu lesen
1 
(5) Basics of the C++ Programming Language 
Nico Ludwig (@ersatzteilchen)
2 
TOC 
● (5) Basics of the C++ Programming Language 
– The Heap: Dynamic Memory and dynamic Array Allocation 
– Automatic versus Dynamic Arrays 
– A Glimpse of the Topic "Stack versus Heap" 
● "Geometric" Properties of the Heap and the Stack 
– Lost Pointers and Memory Leaks 
– Advanced C-strings: Buffers, Concatenation and Formatting 
● Sources: 
– Bruce Eckel, Thinking in C++ Vol I 
– Bjarne Stroustrup, The C++ Programming Language
3 
Automatic Arrays have a Compile Time fixed Size 
● The size of automatic arrays can't be set at run time: 
int count = 0; 
std::cout<<"How many numbers do you want to enter?"<<std::endl; 
std::cin>>count; 
if (0 < count) { 
int numbers[count]; // Invalid (in C++)! The symbol count must be a compile-time constant! 
for (int i = 0; i < count; ++i) { 
std::cout<<"Enter number: "<<(i + 1)<<std::endl; 
std::cin>>numbers[i]; 
} 
}
4 
The Correct Way of creating dynamic Arrays 
● In C/C++, dynamic memory allocation on the heap is needed in such a case. 
– In C, we access the heap with the functions std::malloc() and std::free() in <cstdlib>. 
– The process of requesting memory manually is called "allocation of memory". 
– std::malloc() creates a block of specified size in the heap memory and returns a void* to this block to the caller. 
● For array creation the []-declarator is not used with std::malloc()! 
● (Dynamically created arrays can have the length 0!) 
– The caller needs to check the returned void* for validity (Did std::malloc() succeed?). 
● The returned void* must not be 0! 
– The caller needs to cast this void* to the correct pointer-type. 
– Then the dynamically created array can be used like an "ordinary" array. 
– When the work is done, the array must be manually freed somewhere in the code. 
● In this course we make a distinction between heap 
and free store. This distinction is not defined by 
the C++ standard. Instead it is used colloquially to 
tell the memory managed by 
std::malloc()/std::free() from that managed by 
new/delete, because they could work in different 
memory locations each.
5 
The Correct Way of creating dynamic Arrays in Code 
● Let's review and correct the example of dynamic array creation: 
int count = 0; 
std::cout<<"How many numbers do you want to enter?"<<std::endl; 
std::cin>>count; 
if (0 < count) { // Create a properly sized block in heap. The function std::malloc() returns a generic 
// pointer (void*) and we have to cast this generic pointer to the type we need. 
int* numbers = static_cast<int*>(std::malloc(sizeof(int) * count)); 
if (numbers) { // Check, whether std::malloc() was successful. 
for (int i = 0; i < count; ++i) { // Loop over the dynamically created array: 
std::cout<<"Enter number: "<<(i + 1)<<std::endl; 
// Use the block like an ordinary array, e.g. with the []-operator: 
std::cin>>numbers[i]; 
} 
std::free(numbers); // When done with the array, it must be freed! 
} 
} 
● Consequently check the success of std::malloc()! 
- This is called defensive programming. 
● Why do we need to cast here? 
● This is the first time we really need to cast. - 
Here we need to cast a pointer to memory of 
raw type to a pointer to memory of the type we 
need. 
● The void* represents a pointer to memory of 
unknown type; casting is required to get a type 
with which we can work. A void* is irrelevant by 
itself, we can't even dereference it. The only 
thing we can do with it is comparing it with other 
pointers or 0. 
● Interestingly the conversion from void* to 
another pointer type is seen as conversion 
between related types, so a static_cast is 
sufficient.
Example: Why dynamic Memory is needed: Returning Arrays 
6 
● Automatic arrays can't be returned from functions: 
int* GetValues() { // Defining a function that returns a pointer to a 
int values[] = {1, 2, 3}; // locally defined array (created on the stack) . 
return values; // This pointer points to the 1st item of values. 
} 
//------------------------------------------------------------------------------------------------------------------- 
int* vals = GetValues(); // Semantically wrong! vals points to a 
std::cout<<"2. val is: "<<vals[1]<<std::endl; // discarded memory location. 
// The array "values" is gone away, vals points to its scraps, probably rubbish! 
● In C/C++, dynamic memory allocation on the heap is needed in such a case. 
– Again, the C way is to use the functions std::malloc() and std::free(). 
– 1. In GetValues() the dynamic array will be created and returned. 
– 2. The caller can then use the returned array. 
– 3. Then the caller has to free the dynamically created array!
7 
The Correct Way of returning Arrays 
● Let's review and correct the example of returning an array: 
int* GetValues() { // Allocate an array of three ints: 
int* values = static_cast<int*>(std::malloc(sizeof(int) * 3)); 
if (values) { // Check std::malloc()'s success and fill the array. Indeed the 
values[0] = 1; // allocation of memory and assigning of array values must be 
values[1] = 2; // separated, when std::malloc() is used (there is no Resource 
values[2] = 3; // Acquisition is Initialization (RAII)). 
} // If std::malloc() failed, let's just "forward" the 0, the caller needs to check for 0! 
return values; // Return the pointer to the heap block (i.e. to the array). 
} 
//---------------------------------------------------------------------------------------------------------------------- 
int* vals = GetValues(); 
if (vals) { // We have to check for nullity again, GetValues() could have failed! 
std::cout<<"2nd value is: "<<vals[1]<<std::endl; // Use vals as array! 
// >2nd value is 2 
std::free(vals); // The caller (!) needs to free vals! 
} 
● Once again: Consequently check the success of 
std::malloc()! - Program defensively! 
● RAII means that a resource, which requires e.g. 
dynamic memory or other operating system 
resources, will be initialized and freed analogous 
to the lifetime of a variable. - Practically it means 
that a resource from dynamic memory can be 
controlled by a variable on the stack! - This can be 
implemented with user defined types.
8 
Heap Functions' Signatures in Detail 
void* malloc(size_t size); // memory allocate in <cstdlib> 
// size – The size of a portion of the heap in bytes. size_t is a typedef for a unit representing a 
// count of bytes on a machine, typically it is of type unsigned int. 
// returns – A generic pointer to the allocated portion, or 0 in case of error (e.g. out of memory). 
// The pointer is generic because std::malloc() can't know the type of the allocated contents, it 
// just knows the size that the caller passed and it returns the location of that block in case 
// of success. The pointer must be cast to the type, the caller awaits. - We select the color of 
// the contact lenses to view the block. 
void free(void* ptr); // in <cstdlib> 
// ptr – The pointer to a block of content, allocated with std::malloc(), std::calloc() or 
// std::realloc(). The attempt to free a pointer to a static variable is undefined. Calling std::free() 
// with 0 is allowed, it just has no effect. 
● Can we assume that std::malloc() returns a 
pointer to a gap-free portion in the heap? 
• As far as our current knowledge is concerned: 
yes! It is required, because std::malloc() can be 
used to create arrays, and arrays need to 
represent contiguous blocks of memory.
9 
Wrap up: automatic and dynamic Arrays in Code 
● Creation of automatic arrays: 
int autoArray[100]; 
// This is a simple automatic array with a compile time constant size of 100. 
● Creation and freeing of dynamic arrays: 
int* dynamicArray = static_cast<int*>(std::malloc(sizeof(int) * 100)); 
// - Indeed the syntax looks weird, not even similar to the autoArray example. 
// - The type of the variable we assign to is int-pointer. 
// - The function std::malloc() is used to create a raw memory-block in heap. 
// - std::malloc() returns a generic pointer (void*) to this raw memory-block, it does so, because 
// it doesn't know, what the programmer wants to do. 
// - So, as programmers we need to tell C/C++ that we want to use the allocated memory 
// block as int-array, therefor we need to cast the generic pointer (void*) to int-pointer . - We 
// "put contact lenses on". 
std::free(dynamicArray); // Free the dynamically created array in the right place. 
● Whether objects are stored on the heap or the 
stack is an implementation detail in many other 
languages, not so in C++, because the programer 
explicitly decides, where an object will be created. 
(Annotated C# Language Reference, Anders 
Hejlsberg et. al.)
10 
But, how does returning of "normal" Variables compute? 
● When a local variable is returned from a function, it will be simply copied. 
int GetValue() { // Just returns an int: 
int value = 42; // value is an automatic variable on the stack. 
return value; // Returns value. value will be popped from GetValue()'s stack. 
// Then the content of value will be pushed to the stack of the caller function. 
// In effect value will be copied to its caller when GetValue() returns. 
} 
//------------------------------------------------------------------------------------------------------------------------ 
void Foo() { // Calls GetValue(): 
int val = GetValue(); // The returned int was pushed on Foo()'s stack by GetValue() and 
// will be copied into the variable val. 
} 
● Arrays can't be returned by value, so they can't be copied! 
– Here the story is completely different, we have to use the heap generally! 
● Arrays can also be generated as static arrays 
instead of automatic arrays. A static array can be 
returned from a function. The lifetime of a static 
array is not restricted to a function's local scope.
11 
Stack vs. Heap: It's not a Mystery, just two Concepts 
● The stack is a conceptual place, where local (auto) variables reside. 
– This is a little oversimplification, but each function has its own stack. 
– The lifetime of a stack variable is visible by its scope (i.e. automatic: auto). 
– The stack is controlled by hardware and owned by hardware. 
● The heap is a conceptual place, where all dynamic contents reside. 
– All functions of a program generally use the same heap. 
– Dynamic content must be created by the programmer manually. 
– The heap is controlled by software, the heap manager (std::malloc(), std::free() etc.). 
– There is always an "entity" that is in charge for the allocated heap memory. 
– This "entity" is responsible for explicit freeing the allocated heap memory. 
– In the end, the lifetime of a dynamic content is controlled by the entity's programmer. 
● We'd try to control as less memory as possible manually: using the stack is preferred! 
● What is a scope? 
● See RAII!
12 
Stack vs. Heap: In Memory (RAM) 
● There is the illusion that all the machine's memory is owned by a program. 
– This is not true, each program uses its own portion of memory respectively. 
– But in the following graphics we stick to this illusion. 
● The memory is segmented, different segments have different functions. 
● Esp. the stack and heap segment often have special "geometric" properties: 
– The heap segment resides at lower addresses than the stack segment. 
– The addresses of subsequent stack variables are decreasing. 
● This is called "descending stack". 
– The stack evolves/grows to lower, the heap to greater addresses. 
● In fact, stack and heap grow to meet each other halfway! 
– Compared to the stack, the heap is very big, because dynamic contents are typically bigger than automatic contents (e.g. local 
variables).
13 
Stack vs. Heap: Conventional Locations in Memory 
0 
232 - 1 
Stack segment 
Heap segment 
● Why 232-1? 
● Well 232 is 4294967296 (ca. 4GB), but we have 
to subtract 1 in order to get space for the 
address 0!
14 
The lost Pointer to the Heap Memory in Code 
void F(int count) { 
// Allocating an array of three ints. F() is in charge of the dynamic content, to which 
// p points! 
int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); 
// The auto variable p will go out of scope and will be popped from stack. But the 
// referred dynamic content is still around! 
} 
//------------------------------------------------------------------------------------------------------------------- 
// Calling F(): 
F(3); 
// Oops, nobody did free the dynamic content, to which p was pointing to! Now there is 
// no pointer to the dynamic content in avail. This is a semantic error, a memory leak of 
// sizeof(int) * 3. The compiler will not see any problem here!
15 
The lost Pointer to the Heap Memory in Memory 
Stack segment 
Heap segment 
0 
232 - 1 
0xc0005968 p 
? 0 
1 2 
4B 
4B 
void F(int count) { // Allocating an array of three ints. 
int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); 
if (p) { // Check std::malloc()'s success. 
for (int i = 0; i < count; ++i) { 
p[i] = i; 
} 
} 
} 
// Calling F(): 
F(3); 
// After F() did run: oops! The pointer to the allocated three 
// ints is lost, the allocated memory is orphaned. We have a 
// memory leak of 12B. 
:-(
16 
How to handle dynamic Content responsibly in Code 
int* G(int count) { 
// Allocating an array of three ints. G() is in charge of the dynamic content, to which 
// p points to! 
int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); 
// Returning p. Then G()'s caller is in charge of the dynamic content! 
return p; // The stack variable p will go out of scope and will be popped from the 
// stack. But the referred dynamic content is still around! 
} 
//------------------------------------------------------------------------------------------------------------------- 
// Calling G(): 
int* t = G(3); 
if (t) { // Fine! The returned pointer will be checked and freed correctly. 
std::free(t); 
}
17 
Handling dynamic Content responsibly in Memory 
Stack segment 
Heap segment 
0 
232 - 1 
0xc0005968 p 
1 2 
0 
4B 
4B 
int* G(int count) { // Allocating an array of three ints. 
int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); 
if (p) { // Check std::malloc()'s success. 
for (int i = 0; i < count; ++i) { 
p[i] = i; 
} 
} 
return p; // This time: return p! 
} 
int* t = G(3); // Call G() and receive the pointer. 
if (t) { // Check and free the content (i.e. the 
std::free(t); // memory from the heap). 
} 
// The local variable t is still on the stack. 
t
18 
Potential Problems with Heap Memory 
● It is needed to check, whether allocation was successful! 
● It is needed to free dynamic content in the right place manually. 
– We have to keep in mind that there is no garbage collection in C/C++. 
– So, we should not forget to free dynamically created content! 
– We should free dynamically created content as early as possible, but not too early! 
– We should not free dynamically created content more than once! 
– We should not free dynamically created content that we don't own. 
● It's impossible to distinguish pointers to the stack from pointers to the heap. 
– Don't free pointers to the stack (i.e. pointers not from the heap)! -> It will result in undefined behavior! 
● Wherever function interfaces deal with dynamically content, it should be documented where this memory must be freed. 
Who's the owner? Who's in charge?
19 
More Information about Heap Memory 
● There exist two further useful functions to deal with heap memory (<cstdlib>): 
– std::realloc() resizes a given block of heap memory. 
– std::calloc() allocates a block of size * count and initiates all "items" with 0. 
– The returned value must be checked for 0-pointer and freed with std::free(). 
● Free store in C++: 
– In C++ the heap segment can also be used as free store. 
– The operators new and delete act as interface to the free store. 
– These operators represent C++' way to dynamically allocate/deallocate user defined types. 
– In general, C's heap memory and C++' free store are incompatible. 
● Often 3rd party libraries invent own allocation/deallocation mechanisms: 
– to deal with platform specialities, 
– and/or to encapsulate usage of dynamic contents. 
● std::realloc(): 
• Present items will be preserved up to the 
passed length. 
• Possibly a pointer to another location in the 
heap is returned, rendering the passed address 
invalid. 
• The returned pointer should be checked for 0, 
before it is assigned to the passed pointer 
variable. Don't do it like so: p = std::realloc(p, 
5000)! If reallocation didn't succeed the memory 
to which the passed pointer p refers won't be 
touched.
20 
Putting Heap Memory to work with C-strings 
● As c-strings are char arrays underneath, they share the limits of other arrays: 
– Limitation 1: We can not resize/extend or assign c-strings. 
– Limitation 2: We can not return an automatic c-string variable from a function. 
● These limitations can be solved by usage of the heap memory: 
– Pattern for 1: Create a dynamically sized char-array to hold a modified/resized copy of the original c-string. E.g.: Replace a 
substring of the original c-string. 
– Pattern for 2: Copy a c-string into a dynamically sized char-array and return the pointer from a function. 
● Sidebar: Peculiarities of c-strings, not directly shared with other arrays: 
– C-strings are 0-terminated, so the very last char-array item contains a 0. 
– We can get a c-string's length (std::strlen()), this is impossible with other arrays. 
– As c-strings are const char-arrays, we can't modify them. 
– Indeed we can return a c-string literal from a function! 
● Why is it possible to return a literal c-string from a 
function? 
● C-string literals are stored in the static portion of 
memory (they are an example of a static arrays, 
which were mentioned earlier)! We'll discuss 
static memory in a future lecture.
21 
The Roles of const char[] and char[] 
● When we need to create an array that must be filled afterwards, we can not use arrays with const items. Instead we need 
arrays as modifiable buffers. 
– This is needed, cause we need to assign to the items, in order to modify the content! 
● So, c-strings are of type const char[], their matching buffer type is char[]. 
– The buffers we allocate dynamically for char-based c-strings are always of type char[]. 
● Where c-string functions accept const char*'s as parameters, we can safely pass char[] buffers; they will be decayed to const 
char*. 
● To sum up (char-based c-strings): 
– C-strings are of type const char[], they're not modifiable 
– C-string buffers are of type char[], they're modifiable.
22 
Working with C-strings: Functions for individual Chars 
● A rich set of functions dealing with individual chars can be found in <cctype>. 
● Character predicates (these functions await an int/char and return an int/bool): 
– std::islower(), std::isupper(), std::isalpha(), std::isdigit(), std::isspace() etc. 
char ch = '1'; 
if (std::isdigit(ch)) { 
std::cout<<ch<<" is a digit!"<<std::endl; 
// >1 is a digit 
} 
● Character casing (these functions await an int/char and return an int/char): 
– std::tolower() and std::toupper(), their result must be cast to char for presentation. 
char ch = 'X'; 
// If ch is no upper case letter, the same char will be returned. 
std::cout<<ch<<" as lower case: "<<static_cast<char>(std::tolower(ch))<<std::endl; 
// >X as lower case: x 
● If we pass a non-letter char to 
std::tolower()/std::toupper() the passed char will 
just be returned.
23 
Working with C-strings: Parsing C-strings 
● There exists a set of functions to parse c-strings to fundamental types in <cstdlib>. 
– Parsing means reading a c-string and reinterpret its content e.g. as fundamental type. 
– Most important: std::atoi() (c-string to int) and std::atof() (c-string to double). 
– These functions return 0 in case of error. 
// A c-string that can be interpreted as int: 
const char anInt[] = "42"; 
// Parse the int from anInt's content: 
int theInt = std::atoi(anInt); 
// A c-string that can be interpreted as double: 
const char aDouble[] = "1.786"; 
// Parse the double from aDouble's double: 
double theDouble = std::atof(aDouble);
24 
Working with C-strings: Modify the Case of a C-string 
● Putting it all together, here a first example of c-string modification: 
const char* oldText = "home"; // The original plain c-string. 
// Create a buffer in the heap, large enough to hold the original c-string. The buffer needs a size of: 
// sizeof(char) * (count of chars/letters + one byte for the 0-termination). 
char* newText = static_cast<char*>(std::malloc(sizeof(char) * (std::strlen(oldText) + 1))); 
if (newText) { // Check std::malloc()'s success. 
// Loop over the original c-string and store the upper case variant of each char and the 
// 0-termination into newText at the same index. 
for (int i = 0; i < std::strlen(oldText) + 1; ++i) { 
newText[i] = std::toupper(oldText[i]); 
} 
std::cout<<"The modified text: "<<newText<<std::endl; 
// >The modified text: HOME" 
std::free(newText); // Free the buffer. 
}
25 
C-strings: Formatting and Concatenation of C-strings 
● With the function std::sprintf() in <cstdlib> we can create and format c-strings. 
int sprintf(char* buffer, const char* format, ...); // in <cstdlib> 
// buffer – A char buffer that will contain the effectively created c-string content. The content 
// of the buffer is the virtual result of this function; buffer is rather an output parameter, 
// than an input parameter! 
// format – A c-string that contains a format that describes the disguise of the c-string 
// to create. This "format-string" defines a template of the c-string to create, with 
// placeholders of values to be replaced. 
// ... – An arbitrary set of further arguments that are used to "satisfy" and replace the 
// placeholders in the "format-string". (The ...-notation is called "ellipsis" in C++.) 
// returns – The count of resulting chars in buffer (w/o the 0-termination).
26 
C-strings: "Format-strings" and Examples 
● There exist many type field characters acting as format placeholders. 
– But %d and %s (maybe also %p for pointers) are the most important ones: 
char buffer[1000]; // buffer is an automatic fixed buffer of large extend. 
// The placeholder %d awaits an int to be replaced: 
std::sprintf(buffer, "Answer: %d items", 42); 
std::cout<<buffer<<std::endl; // Will print "Answer: 42 items". 
// The placeholder %s awaits another c-string to be replaced: 
std::sprintf(buffer, "It's %s's problem!", "Rick"); 
std::cout<<buffer<<std::endl; // Will print "It's Ricks's problem!". 
// Now concatenation of e.g. three c-strings can be accomplished: 
std::sprintf(buffer, "%s%s%s", "Weyland Yutani", " at ", "LV-426"); 
std::cout<<buffer<<std::endl; // Will print "Weyland Yutani at LV-426". 
– There are different ways to control the format in a more detailed fashion: 
● Additional flags control alignment and padding, also the width and precision can be controlled. 
– If the format-string and the arguments don't match the behavior is undefined. 
● std::sprintf(): 
● Superfluous arguments will be ignored. 
● Too few arguments result in undefined behavior.
27 
C-strings: Formatting C-strings the Dynamic Way 
● In most scenarios we don't know, how large the buffer must be to hold the result. 
– We can define a very large (maybe auto) buffer, but this is neither safe nor efficient. 
– Preferred: we can calculate the buffer length and create it dynamically! 
● Let's learn how this works.
28 
C-strings: Formatting C-strings the Dynamic Way in Code 
● This is a good way to safely concatenate c-strings with efficient memory usage: 
const char s1[] = "Weyland Yutani"; 
const char s2[] = " at "; 
const char s3[] = "LV-426"; 
// Calculate the length of the resulting c-string: 
int countOfChars = std::strlen(s1) + std::strlen(s2) + std::strlen(s3); 
// Allocate buffer with the exact size, sufficient for our situation: 
char* buffer = static_cast<char*>(std::malloc(sizeof(char) * (countOfChars + 1))); 
if (buffer) { // Check std::malloc()'s success then do the concatenation: 
std::sprintf(buffer, "%s%s%s", s1, s2, s3); 
std::cout<<buffer<<std::endl; 
// >Weyland Yutani at LV-426" 
std::free(buffer); // Free buffer. 
}
29 
Thank you!

Weitere ähnliche Inhalte

Was ist angesagt?

C++11 smart pointer
C++11 smart pointerC++11 smart pointer
C++11 smart pointer
Lei Yu
 
C++tutorial
C++tutorialC++tutorial
C++tutorial
dips17
 
Memory Management with Java and C++
Memory Management with Java and C++Memory Management with Java and C++
Memory Management with Java and C++
Mohammad Shaker
 

Was ist angesagt? (20)

What's New in C++ 11/14?
What's New in C++ 11/14?What's New in C++ 11/14?
What's New in C++ 11/14?
 
C++ 11 Features
C++ 11 FeaturesC++ 11 Features
C++ 11 Features
 
C++11 smart pointer
C++11 smart pointerC++11 smart pointer
C++11 smart pointer
 
Regular types in C++
Regular types in C++Regular types in C++
Regular types in C++
 
C++ memory leak detection
C++ memory leak detectionC++ memory leak detection
C++ memory leak detection
 
C++11
C++11C++11
C++11
 
C++11
C++11C++11
C++11
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
 
C++tutorial
C++tutorialC++tutorial
C++tutorial
 
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ..."Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
"Why is there no artificial intelligence yet?" Or, analysis of CNTK tool kit ...
 
C++11 & C++14
C++11 & C++14C++11 & C++14
C++11 & C++14
 
Pointers & References in C++
Pointers & References in C++Pointers & References in C++
Pointers & References in C++
 
C++ references
C++ referencesC++ references
C++ references
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 1
 
Smart Pointers
Smart PointersSmart Pointers
Smart Pointers
 
Memory Management with Java and C++
Memory Management with Java and C++Memory Management with Java and C++
Memory Management with Java and C++
 
What's New in C++ 11?
What's New in C++ 11?What's New in C++ 11?
What's New in C++ 11?
 
C++11
C++11C++11
C++11
 
Memory Management In C++
Memory Management In C++Memory Management In C++
Memory Management In C++
 
C++ 11
C++ 11C++ 11
C++ 11
 

Andere mochten auch

Pointers in c
Pointers in cPointers in c
Pointers in c
Mohd Arif
 
C programming & data structure [arrays & pointers]
C programming & data structure   [arrays & pointers]C programming & data structure   [arrays & pointers]
C programming & data structure [arrays & pointers]
MomenMostafa
 
Patrick Deming Fitness Myths
Patrick Deming   Fitness MythsPatrick Deming   Fitness Myths
Patrick Deming Fitness Myths
rdeming22
 
How to skype in the classroom
How to skype in the classroomHow to skype in the classroom
How to skype in the classroom
nbrown22
 
Certificate in Intermediate Web Site Design
Certificate in Intermediate Web Site DesignCertificate in Intermediate Web Site Design
Certificate in Intermediate Web Site Design
Philip Duhe
 

Andere mochten auch (20)

Module 02 Pointers in C
Module 02 Pointers in CModule 02 Pointers in C
Module 02 Pointers in C
 
Pointers in c
Pointers in cPointers in c
Pointers in c
 
Pointers in c
Pointers in cPointers in c
Pointers in c
 
Pointers in C
Pointers in CPointers in C
Pointers in C
 
Pointers in c
Pointers in cPointers in c
Pointers in c
 
Pointers In C
Pointers In CPointers In C
Pointers In C
 
Introduction to pointers and memory management in C
Introduction to pointers and memory management in CIntroduction to pointers and memory management in C
Introduction to pointers and memory management in C
 
C programming & data structure [arrays & pointers]
C programming & data structure   [arrays & pointers]C programming & data structure   [arrays & pointers]
C programming & data structure [arrays & pointers]
 
C programming - Pointers
C programming - PointersC programming - Pointers
C programming - Pointers
 
C Pointers
C PointersC Pointers
C Pointers
 
Mpa_SergioA.yFelipe
Mpa_SergioA.yFelipeMpa_SergioA.yFelipe
Mpa_SergioA.yFelipe
 
Patrick Deming Fitness Myths
Patrick Deming   Fitness MythsPatrick Deming   Fitness Myths
Patrick Deming Fitness Myths
 
How to skype in the classroom
How to skype in the classroomHow to skype in the classroom
How to skype in the classroom
 
Los valores
Los valoresLos valores
Los valores
 
QUE ES EL PODCAST
QUE ES EL PODCASTQUE ES EL PODCAST
QUE ES EL PODCAST
 
Mi ml 160 & ml-300 - 14 id - Servicio Tecnico Fagor
Mi ml 160 & ml-300 - 14 id - Servicio Tecnico FagorMi ml 160 & ml-300 - 14 id - Servicio Tecnico Fagor
Mi ml 160 & ml-300 - 14 id - Servicio Tecnico Fagor
 
Certificate in Intermediate Web Site Design
Certificate in Intermediate Web Site DesignCertificate in Intermediate Web Site Design
Certificate in Intermediate Web Site Design
 
Catalogo ExpressMedical
Catalogo ExpressMedicalCatalogo ExpressMedical
Catalogo ExpressMedical
 
Windows 7
Windows 7Windows 7
Windows 7
 
Mi rh 50 - Servicio Tecnico Fagor
Mi rh 50 - Servicio Tecnico FagorMi rh 50 - Servicio Tecnico Fagor
Mi rh 50 - Servicio Tecnico Fagor
 

Ähnlich wie (5) cpp dynamic memory_arrays_and_c-strings

Dynamic memory allocation in c++
Dynamic memory allocation in c++Dynamic memory allocation in c++
Dynamic memory allocation in c++
Tech_MX
 
C aptitude questions
C aptitude questionsC aptitude questions
C aptitude questions
Srikanth
 
C - aptitude3
C - aptitude3C - aptitude3
C - aptitude3
Srikanth
 

Ähnlich wie (5) cpp dynamic memory_arrays_and_c-strings (20)

Introduction to c part -3
Introduction to c   part -3Introduction to c   part -3
Introduction to c part -3
 
Dynamic memory allocation in c++
Dynamic memory allocation in c++Dynamic memory allocation in c++
Dynamic memory allocation in c++
 
dynamic-allocation.pdf
dynamic-allocation.pdfdynamic-allocation.pdf
dynamic-allocation.pdf
 
Dynamic memory allocation
Dynamic memory allocationDynamic memory allocation
Dynamic memory allocation
 
(4) cpp automatic arrays_pointers_c-strings
(4) cpp automatic arrays_pointers_c-strings(4) cpp automatic arrays_pointers_c-strings
(4) cpp automatic arrays_pointers_c-strings
 
(2) collections algorithms
(2) collections algorithms(2) collections algorithms
(2) collections algorithms
 
C aptitude questions
C aptitude questionsC aptitude questions
C aptitude questions
 
C - aptitude3
C - aptitude3C - aptitude3
C - aptitude3
 
Quiz 9
Quiz 9Quiz 9
Quiz 9
 
Linked list
Linked listLinked list
Linked list
 
A nice 64-bit error in C
A  nice 64-bit error in CA  nice 64-bit error in C
A nice 64-bit error in C
 
Dynamic Memory allocation
Dynamic Memory allocationDynamic Memory allocation
Dynamic Memory allocation
 
Memory Management.pptx
Memory Management.pptxMemory Management.pptx
Memory Management.pptx
 
PF UE LEC 7 Pointers programming fundamentals (2).pptx
PF UE LEC 7 Pointers programming fundamentals (2).pptxPF UE LEC 7 Pointers programming fundamentals (2).pptx
PF UE LEC 7 Pointers programming fundamentals (2).pptx
 
(3) cpp abstractions more_on_user_defined_types
(3) cpp abstractions more_on_user_defined_types(3) cpp abstractions more_on_user_defined_types
(3) cpp abstractions more_on_user_defined_types
 
Introduction to C#
Introduction to C#Introduction to C#
Introduction to C#
 
C interview questions
C interview questionsC interview questions
C interview questions
 
Clanguage
ClanguageClanguage
Clanguage
 
C++_notes.pdf
C++_notes.pdfC++_notes.pdf
C++_notes.pdf
 
C++ Training
C++ TrainingC++ Training
C++ Training
 

Mehr von Nico Ludwig

New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
Nico Ludwig
 

Mehr von Nico Ludwig (20)

Grundkurs fuer excel_part_v
Grundkurs fuer excel_part_vGrundkurs fuer excel_part_v
Grundkurs fuer excel_part_v
 
Grundkurs fuer excel_part_iv
Grundkurs fuer excel_part_ivGrundkurs fuer excel_part_iv
Grundkurs fuer excel_part_iv
 
Grundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iiiGrundkurs fuer excel_part_iii
Grundkurs fuer excel_part_iii
 
Grundkurs fuer excel_part_ii
Grundkurs fuer excel_part_iiGrundkurs fuer excel_part_ii
Grundkurs fuer excel_part_ii
 
Grundkurs fuer excel_part_i
Grundkurs fuer excel_part_iGrundkurs fuer excel_part_i
Grundkurs fuer excel_part_i
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
 
(2) gui drawing
(2) gui drawing(2) gui drawing
(2) gui drawing
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
 
(1) gui history_of_interactivity
(1) gui history_of_interactivity(1) gui history_of_interactivity
(1) gui history_of_interactivity
 
New c sharp4_features_part_vi
New c sharp4_features_part_viNew c sharp4_features_part_vi
New c sharp4_features_part_vi
 
New c sharp4_features_part_v
New c sharp4_features_part_vNew c sharp4_features_part_v
New c sharp4_features_part_v
 
New c sharp4_features_part_iv
New c sharp4_features_part_ivNew c sharp4_features_part_iv
New c sharp4_features_part_iv
 
New c sharp4_features_part_iii
New c sharp4_features_part_iiiNew c sharp4_features_part_iii
New c sharp4_features_part_iii
 
New c sharp4_features_part_ii
New c sharp4_features_part_iiNew c sharp4_features_part_ii
New c sharp4_features_part_ii
 
New c sharp4_features_part_i
New c sharp4_features_part_iNew c sharp4_features_part_i
New c sharp4_features_part_i
 
New c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_vNew c sharp3_features_(linq)_part_v
New c sharp3_features_(linq)_part_v
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
 
New c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_ivNew c sharp3_features_(linq)_part_iv
New c sharp3_features_(linq)_part_iv
 
New c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iiiNew c sharp3_features_(linq)_part_iii
New c sharp3_features_(linq)_part_iii
 
New c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_iiNew c sharp3_features_(linq)_part_ii
New c sharp3_features_(linq)_part_ii
 

Kürzlich hochgeladen

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Kürzlich hochgeladen (20)

The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

(5) cpp dynamic memory_arrays_and_c-strings

  • 1. 1 (5) Basics of the C++ Programming Language Nico Ludwig (@ersatzteilchen)
  • 2. 2 TOC ● (5) Basics of the C++ Programming Language – The Heap: Dynamic Memory and dynamic Array Allocation – Automatic versus Dynamic Arrays – A Glimpse of the Topic "Stack versus Heap" ● "Geometric" Properties of the Heap and the Stack – Lost Pointers and Memory Leaks – Advanced C-strings: Buffers, Concatenation and Formatting ● Sources: – Bruce Eckel, Thinking in C++ Vol I – Bjarne Stroustrup, The C++ Programming Language
  • 3. 3 Automatic Arrays have a Compile Time fixed Size ● The size of automatic arrays can't be set at run time: int count = 0; std::cout<<"How many numbers do you want to enter?"<<std::endl; std::cin>>count; if (0 < count) { int numbers[count]; // Invalid (in C++)! The symbol count must be a compile-time constant! for (int i = 0; i < count; ++i) { std::cout<<"Enter number: "<<(i + 1)<<std::endl; std::cin>>numbers[i]; } }
  • 4. 4 The Correct Way of creating dynamic Arrays ● In C/C++, dynamic memory allocation on the heap is needed in such a case. – In C, we access the heap with the functions std::malloc() and std::free() in <cstdlib>. – The process of requesting memory manually is called "allocation of memory". – std::malloc() creates a block of specified size in the heap memory and returns a void* to this block to the caller. ● For array creation the []-declarator is not used with std::malloc()! ● (Dynamically created arrays can have the length 0!) – The caller needs to check the returned void* for validity (Did std::malloc() succeed?). ● The returned void* must not be 0! – The caller needs to cast this void* to the correct pointer-type. – Then the dynamically created array can be used like an "ordinary" array. – When the work is done, the array must be manually freed somewhere in the code. ● In this course we make a distinction between heap and free store. This distinction is not defined by the C++ standard. Instead it is used colloquially to tell the memory managed by std::malloc()/std::free() from that managed by new/delete, because they could work in different memory locations each.
  • 5. 5 The Correct Way of creating dynamic Arrays in Code ● Let's review and correct the example of dynamic array creation: int count = 0; std::cout<<"How many numbers do you want to enter?"<<std::endl; std::cin>>count; if (0 < count) { // Create a properly sized block in heap. The function std::malloc() returns a generic // pointer (void*) and we have to cast this generic pointer to the type we need. int* numbers = static_cast<int*>(std::malloc(sizeof(int) * count)); if (numbers) { // Check, whether std::malloc() was successful. for (int i = 0; i < count; ++i) { // Loop over the dynamically created array: std::cout<<"Enter number: "<<(i + 1)<<std::endl; // Use the block like an ordinary array, e.g. with the []-operator: std::cin>>numbers[i]; } std::free(numbers); // When done with the array, it must be freed! } } ● Consequently check the success of std::malloc()! - This is called defensive programming. ● Why do we need to cast here? ● This is the first time we really need to cast. - Here we need to cast a pointer to memory of raw type to a pointer to memory of the type we need. ● The void* represents a pointer to memory of unknown type; casting is required to get a type with which we can work. A void* is irrelevant by itself, we can't even dereference it. The only thing we can do with it is comparing it with other pointers or 0. ● Interestingly the conversion from void* to another pointer type is seen as conversion between related types, so a static_cast is sufficient.
  • 6. Example: Why dynamic Memory is needed: Returning Arrays 6 ● Automatic arrays can't be returned from functions: int* GetValues() { // Defining a function that returns a pointer to a int values[] = {1, 2, 3}; // locally defined array (created on the stack) . return values; // This pointer points to the 1st item of values. } //------------------------------------------------------------------------------------------------------------------- int* vals = GetValues(); // Semantically wrong! vals points to a std::cout<<"2. val is: "<<vals[1]<<std::endl; // discarded memory location. // The array "values" is gone away, vals points to its scraps, probably rubbish! ● In C/C++, dynamic memory allocation on the heap is needed in such a case. – Again, the C way is to use the functions std::malloc() and std::free(). – 1. In GetValues() the dynamic array will be created and returned. – 2. The caller can then use the returned array. – 3. Then the caller has to free the dynamically created array!
  • 7. 7 The Correct Way of returning Arrays ● Let's review and correct the example of returning an array: int* GetValues() { // Allocate an array of three ints: int* values = static_cast<int*>(std::malloc(sizeof(int) * 3)); if (values) { // Check std::malloc()'s success and fill the array. Indeed the values[0] = 1; // allocation of memory and assigning of array values must be values[1] = 2; // separated, when std::malloc() is used (there is no Resource values[2] = 3; // Acquisition is Initialization (RAII)). } // If std::malloc() failed, let's just "forward" the 0, the caller needs to check for 0! return values; // Return the pointer to the heap block (i.e. to the array). } //---------------------------------------------------------------------------------------------------------------------- int* vals = GetValues(); if (vals) { // We have to check for nullity again, GetValues() could have failed! std::cout<<"2nd value is: "<<vals[1]<<std::endl; // Use vals as array! // >2nd value is 2 std::free(vals); // The caller (!) needs to free vals! } ● Once again: Consequently check the success of std::malloc()! - Program defensively! ● RAII means that a resource, which requires e.g. dynamic memory or other operating system resources, will be initialized and freed analogous to the lifetime of a variable. - Practically it means that a resource from dynamic memory can be controlled by a variable on the stack! - This can be implemented with user defined types.
  • 8. 8 Heap Functions' Signatures in Detail void* malloc(size_t size); // memory allocate in <cstdlib> // size – The size of a portion of the heap in bytes. size_t is a typedef for a unit representing a // count of bytes on a machine, typically it is of type unsigned int. // returns – A generic pointer to the allocated portion, or 0 in case of error (e.g. out of memory). // The pointer is generic because std::malloc() can't know the type of the allocated contents, it // just knows the size that the caller passed and it returns the location of that block in case // of success. The pointer must be cast to the type, the caller awaits. - We select the color of // the contact lenses to view the block. void free(void* ptr); // in <cstdlib> // ptr – The pointer to a block of content, allocated with std::malloc(), std::calloc() or // std::realloc(). The attempt to free a pointer to a static variable is undefined. Calling std::free() // with 0 is allowed, it just has no effect. ● Can we assume that std::malloc() returns a pointer to a gap-free portion in the heap? • As far as our current knowledge is concerned: yes! It is required, because std::malloc() can be used to create arrays, and arrays need to represent contiguous blocks of memory.
  • 9. 9 Wrap up: automatic and dynamic Arrays in Code ● Creation of automatic arrays: int autoArray[100]; // This is a simple automatic array with a compile time constant size of 100. ● Creation and freeing of dynamic arrays: int* dynamicArray = static_cast<int*>(std::malloc(sizeof(int) * 100)); // - Indeed the syntax looks weird, not even similar to the autoArray example. // - The type of the variable we assign to is int-pointer. // - The function std::malloc() is used to create a raw memory-block in heap. // - std::malloc() returns a generic pointer (void*) to this raw memory-block, it does so, because // it doesn't know, what the programmer wants to do. // - So, as programmers we need to tell C/C++ that we want to use the allocated memory // block as int-array, therefor we need to cast the generic pointer (void*) to int-pointer . - We // "put contact lenses on". std::free(dynamicArray); // Free the dynamically created array in the right place. ● Whether objects are stored on the heap or the stack is an implementation detail in many other languages, not so in C++, because the programer explicitly decides, where an object will be created. (Annotated C# Language Reference, Anders Hejlsberg et. al.)
  • 10. 10 But, how does returning of "normal" Variables compute? ● When a local variable is returned from a function, it will be simply copied. int GetValue() { // Just returns an int: int value = 42; // value is an automatic variable on the stack. return value; // Returns value. value will be popped from GetValue()'s stack. // Then the content of value will be pushed to the stack of the caller function. // In effect value will be copied to its caller when GetValue() returns. } //------------------------------------------------------------------------------------------------------------------------ void Foo() { // Calls GetValue(): int val = GetValue(); // The returned int was pushed on Foo()'s stack by GetValue() and // will be copied into the variable val. } ● Arrays can't be returned by value, so they can't be copied! – Here the story is completely different, we have to use the heap generally! ● Arrays can also be generated as static arrays instead of automatic arrays. A static array can be returned from a function. The lifetime of a static array is not restricted to a function's local scope.
  • 11. 11 Stack vs. Heap: It's not a Mystery, just two Concepts ● The stack is a conceptual place, where local (auto) variables reside. – This is a little oversimplification, but each function has its own stack. – The lifetime of a stack variable is visible by its scope (i.e. automatic: auto). – The stack is controlled by hardware and owned by hardware. ● The heap is a conceptual place, where all dynamic contents reside. – All functions of a program generally use the same heap. – Dynamic content must be created by the programmer manually. – The heap is controlled by software, the heap manager (std::malloc(), std::free() etc.). – There is always an "entity" that is in charge for the allocated heap memory. – This "entity" is responsible for explicit freeing the allocated heap memory. – In the end, the lifetime of a dynamic content is controlled by the entity's programmer. ● We'd try to control as less memory as possible manually: using the stack is preferred! ● What is a scope? ● See RAII!
  • 12. 12 Stack vs. Heap: In Memory (RAM) ● There is the illusion that all the machine's memory is owned by a program. – This is not true, each program uses its own portion of memory respectively. – But in the following graphics we stick to this illusion. ● The memory is segmented, different segments have different functions. ● Esp. the stack and heap segment often have special "geometric" properties: – The heap segment resides at lower addresses than the stack segment. – The addresses of subsequent stack variables are decreasing. ● This is called "descending stack". – The stack evolves/grows to lower, the heap to greater addresses. ● In fact, stack and heap grow to meet each other halfway! – Compared to the stack, the heap is very big, because dynamic contents are typically bigger than automatic contents (e.g. local variables).
  • 13. 13 Stack vs. Heap: Conventional Locations in Memory 0 232 - 1 Stack segment Heap segment ● Why 232-1? ● Well 232 is 4294967296 (ca. 4GB), but we have to subtract 1 in order to get space for the address 0!
  • 14. 14 The lost Pointer to the Heap Memory in Code void F(int count) { // Allocating an array of three ints. F() is in charge of the dynamic content, to which // p points! int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); // The auto variable p will go out of scope and will be popped from stack. But the // referred dynamic content is still around! } //------------------------------------------------------------------------------------------------------------------- // Calling F(): F(3); // Oops, nobody did free the dynamic content, to which p was pointing to! Now there is // no pointer to the dynamic content in avail. This is a semantic error, a memory leak of // sizeof(int) * 3. The compiler will not see any problem here!
  • 15. 15 The lost Pointer to the Heap Memory in Memory Stack segment Heap segment 0 232 - 1 0xc0005968 p ? 0 1 2 4B 4B void F(int count) { // Allocating an array of three ints. int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); if (p) { // Check std::malloc()'s success. for (int i = 0; i < count; ++i) { p[i] = i; } } } // Calling F(): F(3); // After F() did run: oops! The pointer to the allocated three // ints is lost, the allocated memory is orphaned. We have a // memory leak of 12B. :-(
  • 16. 16 How to handle dynamic Content responsibly in Code int* G(int count) { // Allocating an array of three ints. G() is in charge of the dynamic content, to which // p points to! int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); // Returning p. Then G()'s caller is in charge of the dynamic content! return p; // The stack variable p will go out of scope and will be popped from the // stack. But the referred dynamic content is still around! } //------------------------------------------------------------------------------------------------------------------- // Calling G(): int* t = G(3); if (t) { // Fine! The returned pointer will be checked and freed correctly. std::free(t); }
  • 17. 17 Handling dynamic Content responsibly in Memory Stack segment Heap segment 0 232 - 1 0xc0005968 p 1 2 0 4B 4B int* G(int count) { // Allocating an array of three ints. int* p = static_cast<int*>(std::malloc(sizeof(int) * count)); if (p) { // Check std::malloc()'s success. for (int i = 0; i < count; ++i) { p[i] = i; } } return p; // This time: return p! } int* t = G(3); // Call G() and receive the pointer. if (t) { // Check and free the content (i.e. the std::free(t); // memory from the heap). } // The local variable t is still on the stack. t
  • 18. 18 Potential Problems with Heap Memory ● It is needed to check, whether allocation was successful! ● It is needed to free dynamic content in the right place manually. – We have to keep in mind that there is no garbage collection in C/C++. – So, we should not forget to free dynamically created content! – We should free dynamically created content as early as possible, but not too early! – We should not free dynamically created content more than once! – We should not free dynamically created content that we don't own. ● It's impossible to distinguish pointers to the stack from pointers to the heap. – Don't free pointers to the stack (i.e. pointers not from the heap)! -> It will result in undefined behavior! ● Wherever function interfaces deal with dynamically content, it should be documented where this memory must be freed. Who's the owner? Who's in charge?
  • 19. 19 More Information about Heap Memory ● There exist two further useful functions to deal with heap memory (<cstdlib>): – std::realloc() resizes a given block of heap memory. – std::calloc() allocates a block of size * count and initiates all "items" with 0. – The returned value must be checked for 0-pointer and freed with std::free(). ● Free store in C++: – In C++ the heap segment can also be used as free store. – The operators new and delete act as interface to the free store. – These operators represent C++' way to dynamically allocate/deallocate user defined types. – In general, C's heap memory and C++' free store are incompatible. ● Often 3rd party libraries invent own allocation/deallocation mechanisms: – to deal with platform specialities, – and/or to encapsulate usage of dynamic contents. ● std::realloc(): • Present items will be preserved up to the passed length. • Possibly a pointer to another location in the heap is returned, rendering the passed address invalid. • The returned pointer should be checked for 0, before it is assigned to the passed pointer variable. Don't do it like so: p = std::realloc(p, 5000)! If reallocation didn't succeed the memory to which the passed pointer p refers won't be touched.
  • 20. 20 Putting Heap Memory to work with C-strings ● As c-strings are char arrays underneath, they share the limits of other arrays: – Limitation 1: We can not resize/extend or assign c-strings. – Limitation 2: We can not return an automatic c-string variable from a function. ● These limitations can be solved by usage of the heap memory: – Pattern for 1: Create a dynamically sized char-array to hold a modified/resized copy of the original c-string. E.g.: Replace a substring of the original c-string. – Pattern for 2: Copy a c-string into a dynamically sized char-array and return the pointer from a function. ● Sidebar: Peculiarities of c-strings, not directly shared with other arrays: – C-strings are 0-terminated, so the very last char-array item contains a 0. – We can get a c-string's length (std::strlen()), this is impossible with other arrays. – As c-strings are const char-arrays, we can't modify them. – Indeed we can return a c-string literal from a function! ● Why is it possible to return a literal c-string from a function? ● C-string literals are stored in the static portion of memory (they are an example of a static arrays, which were mentioned earlier)! We'll discuss static memory in a future lecture.
  • 21. 21 The Roles of const char[] and char[] ● When we need to create an array that must be filled afterwards, we can not use arrays with const items. Instead we need arrays as modifiable buffers. – This is needed, cause we need to assign to the items, in order to modify the content! ● So, c-strings are of type const char[], their matching buffer type is char[]. – The buffers we allocate dynamically for char-based c-strings are always of type char[]. ● Where c-string functions accept const char*'s as parameters, we can safely pass char[] buffers; they will be decayed to const char*. ● To sum up (char-based c-strings): – C-strings are of type const char[], they're not modifiable – C-string buffers are of type char[], they're modifiable.
  • 22. 22 Working with C-strings: Functions for individual Chars ● A rich set of functions dealing with individual chars can be found in <cctype>. ● Character predicates (these functions await an int/char and return an int/bool): – std::islower(), std::isupper(), std::isalpha(), std::isdigit(), std::isspace() etc. char ch = '1'; if (std::isdigit(ch)) { std::cout<<ch<<" is a digit!"<<std::endl; // >1 is a digit } ● Character casing (these functions await an int/char and return an int/char): – std::tolower() and std::toupper(), their result must be cast to char for presentation. char ch = 'X'; // If ch is no upper case letter, the same char will be returned. std::cout<<ch<<" as lower case: "<<static_cast<char>(std::tolower(ch))<<std::endl; // >X as lower case: x ● If we pass a non-letter char to std::tolower()/std::toupper() the passed char will just be returned.
  • 23. 23 Working with C-strings: Parsing C-strings ● There exists a set of functions to parse c-strings to fundamental types in <cstdlib>. – Parsing means reading a c-string and reinterpret its content e.g. as fundamental type. – Most important: std::atoi() (c-string to int) and std::atof() (c-string to double). – These functions return 0 in case of error. // A c-string that can be interpreted as int: const char anInt[] = "42"; // Parse the int from anInt's content: int theInt = std::atoi(anInt); // A c-string that can be interpreted as double: const char aDouble[] = "1.786"; // Parse the double from aDouble's double: double theDouble = std::atof(aDouble);
  • 24. 24 Working with C-strings: Modify the Case of a C-string ● Putting it all together, here a first example of c-string modification: const char* oldText = "home"; // The original plain c-string. // Create a buffer in the heap, large enough to hold the original c-string. The buffer needs a size of: // sizeof(char) * (count of chars/letters + one byte for the 0-termination). char* newText = static_cast<char*>(std::malloc(sizeof(char) * (std::strlen(oldText) + 1))); if (newText) { // Check std::malloc()'s success. // Loop over the original c-string and store the upper case variant of each char and the // 0-termination into newText at the same index. for (int i = 0; i < std::strlen(oldText) + 1; ++i) { newText[i] = std::toupper(oldText[i]); } std::cout<<"The modified text: "<<newText<<std::endl; // >The modified text: HOME" std::free(newText); // Free the buffer. }
  • 25. 25 C-strings: Formatting and Concatenation of C-strings ● With the function std::sprintf() in <cstdlib> we can create and format c-strings. int sprintf(char* buffer, const char* format, ...); // in <cstdlib> // buffer – A char buffer that will contain the effectively created c-string content. The content // of the buffer is the virtual result of this function; buffer is rather an output parameter, // than an input parameter! // format – A c-string that contains a format that describes the disguise of the c-string // to create. This "format-string" defines a template of the c-string to create, with // placeholders of values to be replaced. // ... – An arbitrary set of further arguments that are used to "satisfy" and replace the // placeholders in the "format-string". (The ...-notation is called "ellipsis" in C++.) // returns – The count of resulting chars in buffer (w/o the 0-termination).
  • 26. 26 C-strings: "Format-strings" and Examples ● There exist many type field characters acting as format placeholders. – But %d and %s (maybe also %p for pointers) are the most important ones: char buffer[1000]; // buffer is an automatic fixed buffer of large extend. // The placeholder %d awaits an int to be replaced: std::sprintf(buffer, "Answer: %d items", 42); std::cout<<buffer<<std::endl; // Will print "Answer: 42 items". // The placeholder %s awaits another c-string to be replaced: std::sprintf(buffer, "It's %s's problem!", "Rick"); std::cout<<buffer<<std::endl; // Will print "It's Ricks's problem!". // Now concatenation of e.g. three c-strings can be accomplished: std::sprintf(buffer, "%s%s%s", "Weyland Yutani", " at ", "LV-426"); std::cout<<buffer<<std::endl; // Will print "Weyland Yutani at LV-426". – There are different ways to control the format in a more detailed fashion: ● Additional flags control alignment and padding, also the width and precision can be controlled. – If the format-string and the arguments don't match the behavior is undefined. ● std::sprintf(): ● Superfluous arguments will be ignored. ● Too few arguments result in undefined behavior.
  • 27. 27 C-strings: Formatting C-strings the Dynamic Way ● In most scenarios we don't know, how large the buffer must be to hold the result. – We can define a very large (maybe auto) buffer, but this is neither safe nor efficient. – Preferred: we can calculate the buffer length and create it dynamically! ● Let's learn how this works.
  • 28. 28 C-strings: Formatting C-strings the Dynamic Way in Code ● This is a good way to safely concatenate c-strings with efficient memory usage: const char s1[] = "Weyland Yutani"; const char s2[] = " at "; const char s3[] = "LV-426"; // Calculate the length of the resulting c-string: int countOfChars = std::strlen(s1) + std::strlen(s2) + std::strlen(s3); // Allocate buffer with the exact size, sufficient for our situation: char* buffer = static_cast<char*>(std::malloc(sizeof(char) * (countOfChars + 1))); if (buffer) { // Check std::malloc()'s success then do the concatenation: std::sprintf(buffer, "%s%s%s", s1, s2, s3); std::cout<<buffer<<std::endl; // >Weyland Yutani at LV-426" std::free(buffer); // Free buffer. }