Memory Management in C Programming

CS110 Discussion3
Weiming Hu, 
胡洧铭
Agenda
 
C Memory Management
Common Memory Problems
strlen v.s. sizeof
Can We Do Better?
Manage Device Memory
Memory Management in C
 
Program’s address space contains 4 regions
Stack:
 local variables inside functions, grow
downwards.
Heap:
 Space for dynamic data, requested via
“malloc”, grows upwards.
Static data:
 Variables defined outside functions,
does not grow or shrink. But can be modified.
Code: 
Loaded when program starts. Can not be
modified.
Memory Address
(32 bits assumed here)
Example
#include <stdio.h>
#include <stdlib.h>
static
 
const
 
int
 year 
=
 
2023
;
int
 main
(
void
){
    
char
 name
[]
 
=
 
"Jose"
;
    
char
 
*
game 
=
 
"The Elder Scrolls"
;
    
int
 
*
ver 
=
 malloc
(
sizeof
(
int
));
    
*
ver 
=
 
5
;
    
/* Break! */
    
printf
(
"Until %d, %s's favourite game
is %s %d.\n"
,
 year
,
 name
,
 game
,
 
*
ver
);
    
return
 
0
;
}
Expression:
&year _______
name _______
game _______
ver _______
&ver _______
 
static
 
stack
 
heap
 
static
 
stack
Observations
Code, Static 
storage are easy: they never grow or
shrink
Stack
 space is relatively easy: stack frames are created
and destroyed in last-in, first-out (LIFO) order
Managing the heap is tricky
: memory can be allocated
/ deallocated at any time
Agenda
C Memory Management
Common Memory Problems
strlen v.s. sizeof
Can We Do Better?
Manage Device Memory
Common Memory Problems
 
Using uninitialized values
Using memory that you don’t own
Deallocated stack or heap variable
Out-of-bounds reference to stack or heap array
Using 
NULL
 or garbage data as a pointer
Improper use of 
free/realloc 
by messing with the
pointer handle returned by 
malloc/calloc
Memory leaks (you allocated something you forgot to
later free)
Or 
std::vector::push_back
Using Memory You Don’t Own
What is wrong with this code?
int
 
*
ipr
,
 
*
ipw
;
void
 ReadMem
()
 
{
    
int
 i
,
 j
;
    
ipr 
=
 
(
int*
)
 malloc
(
4
 
*
 
sizeof
(
int
));
    
i 
=
 
*(
ipr 
-
 
1000
);
    
j 
=
 
*(
ipr 
+
 
1000
);
    
free
(
ipr
);
}
void
 WriteMem
()
 
{
    
ipw 
=
 
(
int*
)
 malloc
(
5
 
*
 
sizeof
(
int
));
    
*(
ipw 
-
 
1000
)
 
=
 
0
;
    
*(
ipw 
+
 
1000
)
 
=
 
0
;
    
free
(
ipw
);
}
 
Using pointers beyond the range
that had been malloc’d – May look
obvious, but what if mem refs had
been result of pointer arithmetic
that erroneously took them out of
the allocated range?
Using Memory You Don’t Own
What is wrong with this code?
int
 
*
ipr
,
 
*
ipw
;
int
 offset
;
void
 ReadMem
()
 
{
    
int
 i
,
 j
;
    
ipr 
=
 
(
int
*)
 malloc
(
4
 
*
 
sizeof
(
int
));
    
i 
=
 
*(
ipr 
-
 offset
);
    
j 
=
 
*(
ipr 
+
 offset
);
    
free
(
ipr
);
}
void
 WriteMem
()
 
{
    
ipw 
=
 
(
int
*)
 malloc
(
5
 
*
 
sizeof
(
int
));
    
*(
ipw 
-
 offset
)
 
=
 
0
;
    
*(
ipw 
+
 offset
)
 
=
 
0
;
    
free
(
ipw
);
}
 
Using pointers beyond the range
that had been malloc’d – May look
obvious, but what if mem refs had
been result of pointer arithmetic
that erroneously took them out of
the allocated range?
It may be non-obvious in the
program.
Using Memory You Don’t Own
What is wrong with this code?
 
Reference beyond array bounds
void
 StringManipulate
()
 
{
    
const
 
char
 
*
name 
=
 
"
Safety Critical";
    
char
 
*
str 
=
 malloc
(
10
);
    
strcpy
(
str
,
 name
,
 
10
);
    
str
[
10
]
 
=
 
'\0
'
;
    /* Write Beyond Array Bounds */
    
printf
(
"%s\n"
,
 str
);
 
/* print Safety Cri*/
    
/* Read Beyond Array Bounds */
}
Using Memory You Don’t Own
What is wrong with this code?
 
Beyond stack read/write
char
 
*
append
(
const
 
char
*
 s1
,
 
const
 
char
 
*
s2
)
 
{
    
const
 
int
 MAXSIZE 
=
 
128
;
    
char
 result
[
128
];
    
int
 i
=
0
,
 j
=
0
;
    
for
 
(
j
=
0
;
 i
<
MAXSIZE
-
1
 
&&
 j
<
strlen
(
s1
);
 i
++,
j
++)
 
{
        
result
[
i
]
 
=
 s1
[
j
];
    
}
    
for
 
(
j
=
0
;
 i
<
MAXSIZE
-
1
 
&&
 j
<
strlen
(
s2
);
 i
++,
j
++)
 
{
        
result
[
i
]
 
=
 s2
[
j
];
    
}
    
result
[++
i
]
 
=
 
'\0’
;
    
return
 result
;
}
 
result is a local array name – stack memory allocated
 
Function returns pointer to stack memory – won’t be
valid after function returns
Using Memory You Don’t Own
What is wrong with this code?
 
Following a 
NULL
 pointer to mem addr 0!
typedef
 
struct
 node 
{
    
struct
 node
*
 next
;
    
int
 val
;
}
 Node
;
int
 findLastNodeValue
(
Node
*
 head
)
 
{
    
while
 
(
head 
!=
 
NULL
)
 
{
        
head 
=
 head
->
next
;
    
}
    
return
 head
->
val
;
}
Faulty Heap Management
 
 
Memory leak: 
more mallocs than frees
int
 
*
pi
;
void
 foo
()
 
{
    
pi 
=
 malloc
(
8
*
sizeof
(
int
));
    
/* Allocate memory for pi */
    
/* Oops, leaked the old memory pointed to by pi */
    
    
free
(
pi
);
    
/* foo() is done with pi, so free it */
}
void
 main
()
 
{
    
pi 
=
 malloc
(
4
*
sizeof
(
int
));
    
foo
();
    
/* Memory leak: foo leaks it */
    
}
What is wrong with this code?
Faulty Heap Management
 
What is wrong with this code?
int
 
*
plk 
=
 
NULL
;
void
 genPLK
()
 
{
    
plk 
=
 malloc
(
2
 
*
 
sizeof
(
int
));
    
… … …
    
plk
++;
}
 
Potential memory leak – handle has been changed, do you
still have copy of it that can correctly be used in a later free?
Misuse of free()
 
What is wrong with this code?
 
Can’t free non-heap memory;
Can’t free memory that hasn’t been allocated
void
 FreeMemX
()
 
{
    
int
 fnh 
=
 
0
;
    
free
(&
fnh
);
}
void
 FreeMemY
()
 
{
    
int
 
*
fum 
=
 malloc
(
4
 
*
 
sizeof
(
int
));
    free
(
fum
+
1
);
    free
(
fum
);
    
free
(
fum
);
}
Managing the Heap
 
realloc(p,size)
Resize a previously allocated block at p to a new size
If p is 
NULL
, then 
realloc
 behaves like 
malloc
If size is 0, then 
realloc
 behaves like free, deallocating the block
from the heap
Returns new address of the memory block; NOTE: it is likely to have
moved!
calloc(p,size)
Allocation with initialization: 
malloc() 
+ 
memset()
Agenda
 
C Memory Management
Common Memory Problems
strlen v.s. sizeof
Can We Do Better?
Manage Device Memory
strlen
 
v.s. 
sizeof
#include <stdio.h>
#include <string.h>
int
 main
(){
    
/*I use a 64-bit system*/
    
char
*
 ptrStr 
=
 
"sist1"
;
    
char
 listStr1
[]
 
=
 
"sist1"
;
    
char
 listStr2
[
10
]
 
=
 
"sist1"
;
    
printf
(
"%d\n"
,
 
sizeof
(
ptrStr
));
 
/* sizeof: 8, a ptr takes 8 bytes, 64 bits! */
    
printf
(
"%d\n"
,
 strlen
(
ptrStr
));
 
/* strlen: 5 */
    
printf
(
"%d\n"
,
 
sizeof
(
ptrStr 
+
 
2
));
 
/* sizeof: 8, a ptr takes 8 bytes, 64 bits! */
    
printf
(
"%d\n"
,
 
sizeof
(*(
ptrStr 
+
 
2
)));
 
/* sizeof: 1 */
    
printf
(
"%d\n"
,
 strlen
(
ptrStr 
+
 
2
));
 
/* strlen: 3 */
    
printf
(
"%d\n"
,
 
sizeof
(
listStr1
));
 
/* sizeof:6 */
    
printf
(
"%d\n"
,
 strlen
(
listStr1
));
 
/* strlen:5 */
    
printf
(
"%d\n"
,
 
sizeof
(
listStr2
));
 
/* sizeof: 10 */
    
printf
(
"%d\n"
,
 strlen
(
listStr2
));
 
/* strlen: 5 */
    
return
 
0
;
}
Agenda
 
C Memory Management
Common Memory Problems
strlen v.s. sizeof
Can We Do Better?
Manage Device Memory
Can We Do Better?
 
Many language implements more advanced memory management
C++: Smart pointers, RAII, …
https://web.stanford.edu/class/archive/cs/cs106l/cs106l.1192/lectures/lecture15/15_RAII.pdf
Rust: Ownerships – References and Borrowing
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
Java, Python, …: Garbage Collection
https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
Agenda
 
C Memory Management
Common Memory Problems
strlen v.s. sizeof
Can We Do Better?
Manage Device Memory
Manage Device Memory
 
Examples: Parallel Computing, Deep
Learning, …
Use GPU / Device memory:
#include <stdio.h>
int
 main
(){
    
int
 size_array 
=
 
1024
;
    
int
 
*
h_a
,
 
*
d_a
;
    
h_a 
=
 
(
int
*)
malloc
(
size_array 
*
 
sizeof
(
int
));
    
cudaMalloc
((
void
**)&
d_a
,
 size_array 
*
 
sizeof
(
int
));
    
for
(
int
 i 
=
 
0
;
 i 
<
 size_array
;
 i
++)
        
h_a
[
i
]
 
=
 i
;
    cudaMemcpy
(
d_a
,
 h_a
,
 size_array 
*
 
sizeof
(
int
),
 cudaMemcpyHostToDevice
);
    
/* Call CUDA Kernel Function*/
    
cudaMemcpy
(
h_a
,
 d_a
,
 size_array 
*
 
sizeof
(
int
),
 cudaMemcpyDeviceToHost
);
    free
(
h_a
);
    
cudaFree
(
d_a
);
    
return
 
0
;
}
1.
Copy data to GPU memory
2.
CPU instructs the GPU (kernel configuration
and launching)
3.
Data processed by many cores in parallel
4.
Copy result back to main memory
Parallel Implementation of Grayscale Conversion in
Graphics Hardware, 2011
Conclusion
 
All data is in memory
Each memory location has an address to use to refer to it and a value
stored in it
Pointer
 is a C version (abstraction) of a data address
*
 “follows” a pointer to its value
&
 gets the address of a value
Arrays and strings are implemented as variations on pointers
C is an efficient language, but leaves safety to the programmer
Variables not automatically initialized
Use pointers with care: they are a common source of bugs in programs
Conclusion Cont’d
 
C has three main memory segments in which to
allocate data
Static Data
: 
Variables outside functions
Stack: 
Variables local to function
Heap
:
 Objects explicitly malloced/freed.
Heap
 data is biggest source of BUGs in C code
Slide Note
Embed
Share

The discussion covers various aspects of memory management in C programming, including common memory problems and examples. It delves into memory regions, stack and heap management, and static data. The examples illustrate concepts like static storage, heap allocation, and common pitfalls to avoid. Proper memory handling is crucial to avoid issues like memory leaks, uninitialized values, out-of-bounds references, and improper use of memory functions.

  • Memory Management
  • C Programming
  • Common Problems
  • Dynamic Memory Allocation
  • Static Data

Uploaded on Sep 14, 2024 | 1 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. CS110 Discussion3 Weiming Hu,

  2. Agenda C Memory Management Common Memory Problems strlen v.s. sizeof Can We Do Better? Manage Device Memory

  3. Memory Management in C Memory Address (32 bits assumed here) Program s address space contains 4 regions Stack: local variables inside functions, grow downwards. Heap: Space for dynamic data, requested via malloc , grows upwards. Static data: Variables defined outside functions, does not grow or shrink. But can be modified. Code: Loaded when program starts. Can not be modified.

  4. Example #include <stdio.h> #include <stdlib.h> static const int year = 2023; Expression: static &year _______ int main(void){ char name[] = "Jose"; char *game = "The Elder Scrolls"; int *ver = malloc(sizeof(int)); *ver = 5; /* Break! */ printf("Until %d, %s's favourite game is %s %d.\n", year, name, game, *ver); return 0; } stack name _______ static game _______ heap ver _______ stack &ver _______

  5. Observations Code, Static storage are easy: they never grow or shrink Stack space is relatively easy: stack frames are created and destroyed in last-in, first-out (LIFO) order Managing the heap is tricky: memory can be allocated / deallocated at any time

  6. Agenda C Memory Management Common Memory Problems strlen v.s. sizeof Can We Do Better? Manage Device Memory

  7. Common Memory Problems Using uninitialized values Using memory that you don t own Deallocated stack or heap variable Out-of-bounds reference to stack or heap array Using NULL or garbage data as a pointer Improper use of free/realloc by messing with the pointer handle returned by malloc/calloc Memory leaks (you allocated something you forgot to later free) Or std::vector::push_back

  8. Using Memory You Dont Own What is wrong with this code? int *ipr, *ipw; void ReadMem() { int i, j; ipr = (int*) malloc(4 * sizeof(int)); i = *(ipr - 1000); j = *(ipr + 1000); free(ipr); } void WriteMem() { ipw = (int*) malloc(5 * sizeof(int)); *(ipw - 1000) = 0; *(ipw + 1000) = 0; free(ipw); } Using pointers beyond the range that had been malloc d May look obvious, but what if mem refs had been result of pointer arithmetic that erroneously took them out of the allocated range?

  9. Using Memory You Dont Own What is wrong with this code? int *ipr, *ipw; int offset; void ReadMem() { int i, j; ipr = (int*) malloc(4 * sizeof(int)); i = *(ipr - offset); j = *(ipr + offset); free(ipr); } void WriteMem() { ipw = (int*) malloc(5 * sizeof(int)); *(ipw - offset) = 0; *(ipw + offset) = 0; free(ipw); } Using pointers beyond the range that had been malloc d May look obvious, but what if mem refs had been result of pointer arithmetic that erroneously took them out of the allocated range? It may be non-obvious in the program.

  10. Using Memory You Dont Own What is wrong with this code? void StringManipulate() { const char *name = "Safety Critical"; char *str = malloc(10); strcpy(str, name, 10); str[10] = '\0'; /* Write Beyond Array Bounds */ printf("%s\n", str); /* print Safety Cri*/ /* Read Beyond Array Bounds */ } Reference beyond array bounds

  11. Using Memory You Dont Own What is wrong with this code? char *append(const char* s1, const char *s2) { const int MAXSIZE = 128; char result[128]; int i=0, j=0; for (j=0; i<MAXSIZE-1 && j<strlen(s1); i++,j++) { result[i] = s1[j]; } for (j=0; i<MAXSIZE-1 && j<strlen(s2); i++,j++) { result[i] = s2[j]; } result[++i] = '\0 ; return result; } result is a local array name stack memory allocated Function returns pointer to stack memory won t be valid after function returns Beyond stack read/write

  12. Using Memory You Dont Own What is wrong with this code? typedef struct node { struct node* next; int val; } Node; int findLastNodeValue(Node* head) { while (head != NULL) { head = head->next; } return head->val; } Following a NULL pointer to mem addr 0!

  13. Faulty Heap Management What is wrong with this code? int *pi; void foo() { pi = malloc(8*sizeof(int)); /* Allocate memory for pi */ /* Oops, leaked the old memory pointed to by pi */ free(pi); /* foo() is done with pi, so free it */ } void main() { pi = malloc(4*sizeof(int)); foo(); /* Memory leak: foo leaks it */ } Memory leak: more mallocs than frees

  14. Faulty Heap Management What is wrong with this code? int *plk = NULL; void genPLK() { plk = malloc(2 * sizeof(int)); plk++; } Potential memory leak handle has been changed, do you still have copy of it that can correctly be used in a later free?

  15. Misuse of free() What is wrong with this code? void FreeMemX() { int fnh = 0; free(&fnh); } void FreeMemY() { int *fum = malloc(4 * sizeof(int)); free(fum+1); free(fum); free(fum); } Can t free non-heap memory; Can t free memory that hasn t been allocated

  16. Managing the Heap realloc(p,size) Resize a previously allocated block at p to a new size If p is NULL, then realloc behaves like malloc If size is 0, then realloc behaves like free, deallocating the block from the heap Returns new address of the memory block; NOTE: it is likely to have moved! calloc(p,size) Allocation with initialization: malloc() + memset()

  17. Agenda C Memory Management Common Memory Problems strlen v.s. sizeof Can We Do Better? Manage Device Memory

  18. strlen v.s. sizeof #include <stdio.h> #include <string.h> int main(){ /*I use a 64-bit system*/ char* ptrStr = "sist1"; char listStr1[] = "sist1"; char listStr2[10] = "sist1"; printf("%d\n", sizeof(ptrStr)); /* sizeof: 8, a ptr takes 8 bytes, 64 bits! */ printf("%d\n", strlen(ptrStr)); /* strlen: 5 */ printf("%d\n", sizeof(ptrStr + 2)); /* sizeof: 8, a ptr takes 8 bytes, 64 bits! */ printf("%d\n", sizeof(*(ptrStr + 2))); /* sizeof: 1 */ printf("%d\n", strlen(ptrStr + 2)); /* strlen: 3 */ printf("%d\n", sizeof(listStr1)); /* sizeof:6 */ printf("%d\n", strlen(listStr1)); /* strlen:5 */ printf("%d\n", sizeof(listStr2)); /* sizeof: 10 */ printf("%d\n", strlen(listStr2)); /* strlen: 5 */ return 0; }

  19. Agenda C Memory Management Common Memory Problems strlen v.s. sizeof Can We Do Better? Manage Device Memory

  20. Can We Do Better? Many language implements more advanced memory management C++: Smart pointers, RAII, https://web.stanford.edu/class/archive/cs/cs106l/cs106l.1192/lectures/lecture15/15_RAII.pdf Rust: Ownerships References and Borrowing https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html Java, Python, : Garbage Collection https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

  21. Agenda C Memory Management Common Memory Problems strlen v.s. sizeof Can We Do Better? Manage Device Memory

  22. Manage Device Memory 1. 2. Copy data to GPU memory CPU instructs the GPU (kernel configuration and launching) Data processed by many cores in parallel Copy result back to main memory Parallel Implementation of Grayscale Conversion in Graphics Hardware, 2011 Examples: Parallel Computing, Deep Learning, Use GPU / Device memory: 3. 4. #include <stdio.h> int main(){ int size_array = 1024; int *h_a, *d_a; h_a = (int*)malloc(size_array * sizeof(int)); cudaMalloc((void**)&d_a, size_array * sizeof(int)); for(int i = 0; i < size_array; i++) h_a[i] = i; cudaMemcpy(d_a, h_a, size_array * sizeof(int), cudaMemcpyHostToDevice); /* Call CUDA Kernel Function*/ cudaMemcpy(h_a, d_a, size_array * sizeof(int), cudaMemcpyDeviceToHost); free(h_a); cudaFree(d_a); return 0; }

  23. Conclusion All data is in memory Each memory location has an address to use to refer to it and a value stored in it Pointer is a C version (abstraction) of a data address * follows a pointer to its value & gets the address of a value Arrays and strings are implemented as variations on pointers C is an efficient language, but leaves safety to the programmer Variables not automatically initialized Use pointers with care: they are a common source of bugs in programs

  24. Conclusion Contd C has three main memory segments in which to allocate data Static Data: Variables outside functions Stack: Variables local to function Heap: Objects explicitly malloced/freed. Heap data is biggest source of BUGs in C code

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#