CS计算机代考程序代写 data structure compiler Java memory_mgmnt

memory_mgmnt

C Crash Course (II): C Basics

for System Programming

Presented by
Dr. Shuaiwen Leon Song
USYD Future System Architecture Lab (FSA)
https://shuaiwen-leon-song.github.io/

https://shuaiwen-leon-song.github.io/

FACULTY OF

ENGINEERING

Warmup Contents

What is the printout of this code?

Segmentation fault (core dump) !

Core Dump/Segmentation Fault

Core Dump/Segmentation fault is a specific kind of error caused by accessing memory that

“does not belong to you.”

•When a piece of code tries to do read and write operation in a read only location in memory

or freed block of memory, it is known as core dump.

•It is an error indicating memory corruption.

Six Main Ways:

1. Modifying a string literal (writing to read-only memory)

2. Accessing an address that is freed (not allowed in compiler)

3. Accessing out of array index bounds

4. Improper use of scanf() (input fetched from STDIN is placed in invalid memory,

causing memory corruption)

5. Stack Overflow

6. Dereferencing uninitialized pointer (A pointer must point to valid memory

before accessing it).

What is in text?

A text segment , also known as a code segment or

simply as text, is one of the sections of a program in

an object file or in memory, which contains executable

instructions.

As a memory region, a text segment may be placed

below the heap or stack in order to prevent heaps and

stack overflows from overwriting it.

Usually, the text segment is sharable so that only a

single copy needs to be in memory for frequently

executed programs, such as text editors, the C

compiler, the shells, and so on. Also, the text segment

is often read-only, to prevent a program from

accidentally modifying its instructions.

Examples: string literals defined in functions

const and its pointers defined in functions

Less familiar const

› constprevents the value being modified

– const char *fileheader = “P1”

– fileheader[1] = ‘3’;

› It can be used to help avoid arbitrary changes tomemory

› The value constprotects depends where it appears

– char * const fileheader = “P1”

– fileheader = “P3”;

› You can cast if you know if the memory iswritable

Illegal: change of address value

Illegal: change of char value

char fileheader[] = {‘P’, ‘1’};

const char *dataptr = (char*)fileheader;

char *p = (char*)dataptr;

p[1] = ‘3’;

writable

Non-writable

Dangling pointers

A pointer pointing to a memory location that has been deleted

(or freed) is called dangling pointer.

#include
#include

int* foo(int a,int b)
{
int sum = a + b;

return ∑
}

int main() {
int* addr = foo(5, 6);

}

#include
#include

int* foo(int a,int b)
{
static int sum = a + b;

return ∑
}

int main() {
int* addr = foo(5, 6);

}

You can also do this!
#include
#include

int* foo(int a,int b, int* sum)
{

*sum = a + b;

return sum;
}

int main() {
int *sum = (int*) malloc(sizeof(int)*10);
if (sum == NULL) {

printf(“Memory not allocated.\n”);
exit(0);

}
sum= foo(5, 6, sum);
printf(“%d\n”, *sum);
free(sum);
return 0;

}

Which one causing problems?

Which of the above three functions are likely to cause

problems with pointers?

(A) Only P3

(B) Only P1 and P3

(C) Only P1 and P2

(D) P1, P2 and P3

Try not to return local variable address!
Segmentation fault or program crash

FACULTY OF

ENGINEERING

Pointers

Memory

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

Memory

Random values initially

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

Memory

› a pointer is essentially a variable that
stores a memory address

› we can find out the address of a variable using

the & operator

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

Memory

char initial = ‘A’;

char *initp = &initial

&initial is the address of initial
initp is a pointer to initial

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1

1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1

0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
0 1 0 0 0 1 1 11 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1

variable name: “count”
address of count: 0x1000 = 4,096

0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0
0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1

1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

Clearly, the value of a pointer can

only be determined at run-time.

Somewhere in memory…

Somewhere else in memory…

Label: “ptr”

int count;

int *ptr;

count = 2;

ptr = &count;

printf(”%d\n”, count);

printf(”%d\n”, *ptr);

printf(”%d\n”, &count);

printf(”%d\n”, ptr);

2

2

4096

4096

Label: “count”

Pointers

(notation)› Pointer operators:
– address operator, ‘&’

– indirection operator, ‘*’

Note that these operators are “overloaded”, that is they have
more than one meaning.

– ‘&’ is also used in C as the bitwise ‘AND’ operator

– ‘*’ is also used in C as the multiplication operator

Pointers (notation)

› The indirection operator, ‘*’, is used in a variable
declaration to declare a “pointer to a variable of the
specified type”:

int * countp; /* pointer to an integer */

Type is “a pointer to an integer”

Variable name, “countp”

Pointers (notation)

What do the following
mean?

float * amt;

int ** tricky;

Answers:

A pointer (labeled “amt”) to
a float.

A pointer (labeled “tricky”)
to a pointer to an int.

Pointers (notation)

…prints ‘2’ to standard output.

› The indirection operator, ‘*’, is used to “unravel” the
indirection:

countp points to an integer variable that contains the value 2.

Then…

2
printf(”%d”, *countp);

countp

Unravel the

indirection

Pointers (notation)

What is output in the following?

printf(”%d”, count);

17

printf(”%d”, *countp);

17

printf(”%d”, countp);

Don’t know… but it will be
the address of count.
Why?

17

countp

count

Pointers (notation)

› The address operator, ‘&’, is used to accessthe
address of a variable.

›This completes the picture! A pointer can be

assigned the address of a variable simply:

int * countp = &count;

Declare “a pointer to an integer” called countp

Assign countp the address of count.

Pointers (notation)

Wild pointers: I don’t like it
Uninitialized pointers are known as wild pointers because they point to some arbitrary

memory location and may cause a program to crash or behave badly.

int main()
{
int *p; /* wild pointer */
/* Some unknown memory location is being corrupted.
This should never be done. */
*p = 12;
}

int main()
{
int *p; /* wild pointer */
int a = 10;
p = &a;
*p = 12;
}

This is ok !

Use of pointer notation to manipulate arrays…

char msg[] = ”Hello!”;

char *str = &msg[0];

OR:
char *str = msg;

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

Pointers and arrays

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

msg[0]

str[0]

*str

msg[1]

str[1]

*(str+1)

Examples

Pointer notation leads to some (intimidating?) shortcuts as
part of the C idiom.

Moving through a string:

while (*str != ’\0’)

str++;

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

Examples

The previous example may exploit the fact that C

treats ‘0’ as FALSE:

while (*str)

str++;

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

Examples

› Some mathematical operations are moreconvenient
using pointers

– e.g., array operations

› However, we have only looked at static data. Pointers
are essential in dealing with dynamic data structures.

› Imagine you are writing a texteditor.

– You could estimate the largest line-length and create arrays of
that size (problematic).

– Or you could dynamically allocate memory as needed, using
pointers.

Why use pointers?

›What is the value held by p? and how much
memory is used by p (in bytes)?

› int p;

› char p;

› void foo( int *p )

› char *p;

› char **p;

Revision Pointers

›What is the value held by p? and how much
memory is used by p (in bytes)?

› int p;

› char p;

› void foo( int *p )

› char *p;

› char **p;

› int **p;

› long *p;

› void *p;

› const unsigned long long int * const p;

› bubblebobble ************p;

Revision Pointers

› char *p

– Address to a single char value

– Address to a single char value that is the first in an array

› char *argv[]

– Array of “the type” with unknown length

– Type is char *

› char **argv

– * Address to the first element to an array of type char *

– Then, each element in * is an…

– * address to the first element to an array of type char

char argv[][3]; // oh no!

Pointer interpretation

› Interpretations of int **data;

1. Pointer to pointer to single int value

2. Array of addresses that point to a single int

3. Address that points to one array of int values

4. Array of addresses that point to arrays of int values

Pointer interpretation

› Interpretations of int **data;

1. Pointer to pointer to single int value

2. Array of addresses that point to a single int

3. Address that points to one array of int values

4. Array of addresses that point to arrays of int values

› Thinking about each * as an array:

1. Array size ==1, Array size ==1

2. Array size >=1, Array size == 1

3. Array size ==1, Array size >= 1

4. Array size >=1, Array size >= 1

Pointer interpretation

0x0100 0x0104 0x0105

› int *p = NULL;

› int x[4];

› p = x;

x = 0x0100
0x0101 0x0101 0x0102 0x0103

0 0 0 17

0x0106 0x0107 0x0108 0x0109 0x010A 0x010B 0x010C 0x010D 0x010E

*(p + 0) *(p + 1) *(p + 2)

› Seeking to the nth byte from a starting address?

*(p + 3)

Pointer arithmetic

0x0100 0x0104 0x0105

› int *p = NULL;

› int x[4];

› p = x;

x = 0x0100
0x0101 0x0101 0x0102 0x0103

0 0 0 17

0x0106 0x0107 0x0108 0x0109 0x010A 0x010B 0x010C 0x010D 0x010E

*(p + 0) *(p + 1) *(p + 2) *(p + 3)

› Seeking to the nth byte from a starting address?

void *get_address( sometype *data , int n) {

unsigned char *ptr = (unsigned char*)data;

return (void*)(ptr + n);

}

Pointer arithmetic

Q1

Assume that an int variable takes 4 bytes and a char variable takes 1 byte

(A) Number of elements between two pointer are: 5.

Number of bytes between two pointers are: 20

(B) Number of elements between two pointer are: 20.

Number of bytes between two pointers are: 20

(C) Number of elements between two pointer are: 5.

Number of bytes between two pointers are: 5

(D) Compiler Error

(E) Runtime Error

Q2

(A) Compiler Error

(B) Garbage Value

(C) Runtime Error

(D) G

Q3

(A) 10 20 30 40

(B) Machine Dependent

(C) 10 20

(D) Northing

int arr[4] = {10, 20 ,30,40};
printf(“%d\n”, sizeof(arr));

What is this print out?

Assume it is a 64-bit machine.

16
10 20

Q4

Assuming 32-bit machine:
(A) sizeof arri[] = 3 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 4

(B) sizeof arri[] = 12 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 1

(C) sizeof arri[] = 3 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 1

(D) sizeof arri[] = 12 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 4

Q5

(A) 2 2

(B) 2 1

(C) 0 1

(D) 0 2

Q6

S1: will generate a compilation error

S2: may generate a segmentation fault at runtime depending on the arguments passed

S3: correctly implements the swap procedure for all input pointers referring to integers

stored in memory locations accessible to the process

S4: implements the swap procedure correctly for some but not all valid input pointers

S5: may add or subtract integers and pointers.

(A) S1

(B) S2 and S3

(C) S2 and S4

(D) S2 and S5

Q7

(A) 18

(B) 19

(C) 21

(D) 22

X+y+z= 7+7+5=19

Q8

(A) 12

(B) Compiler Error

(C) Runt Time Error

(D) 0

printf(“%d”, *(int *)ptr);

1.void pointers cannot be dereferenced. It can

however be done using typecasting the void

pointer

2.Pointer arithmetic is not possible on pointers of

void due to lack of concrete value and thus size

Q9

(A)
(geeksquiz, geeksforgeeks) (geeksforgeeks, geeksquiz)

(B)
(geeksforgeeks, geeksquiz) (geeksquiz, geeksforgeeks)

(C)
(geeksquiz, geeksforgeeks) (geeksquiz, geeksforgeeks)

(D)
(geeksforgeeks, geeksquiz) (geeksforgeeks, geeksquiz)

Q10

(A) ab

(B) cd

(C) ef

(D) gh

Memory

• Memory is a long array of 8 bit pieces

called bytes

• This array is indexed from 0 to the number

of bytes in the memory

• Each index is a memory address

0 1 2 3 ……

Memory Areas

• Stack: local variables, function arguments,

return addresses, temporary storage

• Heap: dynamically allocated memory

• Global/static: global variables, static

variables

• Code: program instructions

Memory Layout

stack

heap

static

global

code

End of

memory

0

Free space

The Stack

• In C, all variables local to a function and

function arguments are stored on the stack

• To call a function the code does:

push arguments onto stack

push return address onto stack

jump to function code

The Stack

• Inside the function, the code does the following:

increment the stack pointer to allow

space for the local variables

execute the code

pop local variables and arguments off the stack

push the return result onto the stack

jump to return address

Function call example

0 …

1 123

2 1b345f0

. . .

res = myfun(123);

. . .

argument

MemoryAddress

stack ptr

Return
Address

Function call example

int myfun(int a)

{

int b = 5;

return 0;

}

stack ptr

0 …

1 123

2 1b345f0

5

MemoryAddress

Function call example

int myfun(int a)

{

int b = 5;

return 0;

}

0

0

1

2

stack ptr

MemoryAddress

Memory may be dynamically allocated at

run-time from an area known as “the
heap”.

Unlike the stack, which meets the

temporary storage demands associated

with called functions, the heap is accessed

under direct programmer control.

Heap

We request an allocation

of memory from the heap.

If there is sufficient

contiguous memory

available, we are given the

address of the start of the

allocated memory.

heap

used

free

Pointer

newly

allocated

Q: Where are parts of this program stored?

int a;

int main() {

int b;

int *p;

p = malloc(…)

}

int doit(int c) {

static int d;

}

int a;

int main() {

int b;

int *p;

p = malloc(…)

}

int doit(int c) {

static int d;

}

SUMMARY

Memory allocation is not difficult!

It only causes problems because novice
programmers may not recognise the need to
address it…

Java programmers are less likely to
experience such problems simply because
Java hides the need to deal with this whole
issue.

Memory Management Functions

Memory allocation functions return a “pointer
to void”.

A pointer to void is a “generic” pointer
type. A void * can be converted to any
other pointer type

The pointer must therefore be cast to a

specific type.

Memory allocation functions

Memory allocation functions: malloc

#include

void *malloc(size_t size);

Requests size number of bytes of memory.

Returns a pointer to the allocated memory, if
successful, or a NULL pointer if unsuccessful

Typically defined as:
typedef unsigned int size_t;

A comment on the use of size_t:

Use of size_t replaces the use of more specific

types, such as int, short, etc. This allows the actual

implementation to be system-specific.

The sizeof operator is of type size_t. This is often

used to specify memory requirements, so it makes

sense to have the size argument in memory allocation
functions of type size_t.

int * ptr;

ptr = (int *)malloc(sizeof(int)*20);

ptr

If an int is 4 bytes, then this call

will request 80 bytes of memory

from the heap.

#include

void *calloc(size_t num, size_t size);

calloc

This is similar to malloc except that:

• It has two arguments:
– num specifies the number of “blocks” of contiguous

memory

– size specifies the size of each block

• The allocated memory is cleared (set to ‘0’).

Can be
implemented
by : malloc
and memset

#include

void free(void *ptr);

This is used to de-allocate memory previously

allocated by any of the memory allocation

functions.

free

int * ptr;

ptr = (int *)malloc(sizeof(int)*20);

free((void *)ptr);

Ptr = NULL;

ptr

Memory Leak
Big issues for long-running data center applications, scientific simulations, Daemons
(background process) and servers.

#include

void *realloc(void *ptr, size_t size);

This takes previously-allocated memory and

attempts to resize it.

This may require a new block of memory to be
found, so it returns a new void pointer to memory.

Contents are preserved.

realloc

int * ptr;

ptr = (int *)malloc(sizeof(int)*2);

ptr = (int *)

realloc(ptr, sizeof(int)*200);

ptr

int * ptr;

ptr = (int *)malloc(sizeof(int)*2);

ptr = (int *)

realloc(ptr, sizeof(int)*200);

ptr

You can use realloc to implement free
(): just set the size to 0.

Example

Correct?

Example

Correct?

Dynamically creating structures

struct thing * ptr;

ptr = (struct thing *)malloc(sizeof(struct thing));

/* Do stuff */

ptr->day = mon;

free((void *)ptr);

Ptr = NULL;
This is a some of what Java does

“behind the scenes” on object
creation.

Safety issues

Caution #1:

De-allocate memory that is no longer
required.

While the system should de-allocate

resources on termination, it is good practice

to take control of this process.

In some Java programs there is a noticeable performance dip

when the automatic “garbage collection” functionality kicks in.

Safety issues

Caution #2:

NEVER attempt to de-allocate memory that
has not been allocated!

A common error is to try to free memory that

has already been de-allocated, or was never

allocated in the first instance.

Safety issues

Caution #3:

NEVER try to use memory that has been de-
allocated.

This is also a common error leading to

serious problems.

Safety issues

int* p = malloc(sizeof(int));

free(p);
*p = 5; //segfault here

https://segfault/

Caution #4:

Know your memory allocation requirements!

Use of the sizeof operator addresses the

more obvious problems.

However, a common problem is to forget that a
string includes a ‘\0’ terminating character.

Safety issues

Caution #5:

Check for success!

A failed memory allocation request can lead to
disaster if it is simply assumed to be successful.

Previous examples here have made this
assumption for convenience. This would NOT
qualify as bullet-proof code!

Safety issues

Summary

✓Understand the need for memory allocation

and de-allocation

✓Be able to use relevant C functions for

achieving this

✓ malloc

✓ calloc

✓ realloc

✓ free

✓Be able to allocate and access memory safely

Write a 2d Array

Write a 2d array via single pointer

Using an array of pointers

Using pointer to a pointer

Q1

Q2

Which of the following is true?

(A) “ptr = calloc(m, n)” is equivalent to following

ptr = malloc(m * n);

(B) “ptr = calloc(m, n)” is equivalent to following

ptr = malloc(m * n);

memset(ptr, 0, m * n);

(C) “ptr = calloc(m, n)” is equivalent to following

ptr = malloc(m);

memset(ptr, 0, m);

(D) “ptr = calloc(m, n)” is equivalent to following

ptr = malloc(n);

memset(ptr, 0, n);

Q3

(A) Compiler Error: free can’t be applied on NULL pointer

(B) Memory Leak

(C) Dangling Pointer

(D) The program may crash as free() is called for NULL pointer.

Q4

Which of the following is/are true

(A) calloc() allocates the memory and also initializes the allocates memory to zero,

while memory allocated using malloc() has uninitialized data.

(B) malloc() and memset() can be used to get the same effect as calloc().

(C) calloc() takes two arguments, but malloc takes only 1 argument.

(D) Both malloc() and calloc() return ‘void *’ pointer.

(E) All of the above