key c topics: tutorial pointers, dynamic memory …cs370/spring18/lectures/help...outline •...
TRANSCRIPT
Key C Topics: Tutorial
Pointers, Dynamic Memory
allocation, Valgrind and
Makefile
CS370
Outline
• Pointers in C• & and * operators• Pointers with Arrays and Strings
• Dynamic memory allocation• malloc() and free()• Valgrind tool
• Makefile
What is a Pointer?
• int k; k =2;• ‘k’ is the name given to the memory location which
stores the value 2. As the data type used is int, 4 bytes of memory is reserved for k.
• Internally the memory is identified by an address, which is what ’k’ refers to. This address of ‘k can be accessed by using the & operator, i.e. &k
• int *p = &k;• Here ‘p’ is a pointer variable, hence the
dereferencing (*) operator before it. The pointer variable ’p’ holds the address where the ’k’ holds the value.
• Hence *p = 2 is equivalent to k = 2
What is a Pointer?
Data Type of a Pointer
• *(p+1) = ?
C increments the pointer based on the type of variable it points to. In the above case as it points to int, ‘p’ is incremented by 4, so we have (p+1)=0x100 and *(p+1)=7
Pointers and Arrays
•
•
p = &arr[0];
The symbol arr itself is a pointer to the first
element of the array.
• Hence, arr[i] can also be written as *(arr+i)
Pointers and Arrays
•
•
int arr[3]= 1,2,3; int *p = arr;p is pointing to arr[0](=1);
Step1: printf(“%d”,*p++)
Get value at p: 1 (output)
Increment p: p is now pointing to arr[1]
•
•
Step2: printf(“%d”,*++p)Increment p: p is now pointing to arr[2]
Get value at p: 3 (output)
Step3: printf(“%d”,++*p)Increment value at p and then print it• arr[2]=3+1=4(output)
Pointers and Strings
•
•
A string in C is simply an array of char values
So the functioning of pointers with strings is
same as that with the arrays.
char strA[] = “Ping”;char strB[] = “Pong”;char *pA = strA;
char *pB = strB;
while (*pA) *pB++ = *pA++;*pB = '\0’;;
Pointers and Strings
• Put the reverse of str1 into str2:
char str1[] = "Pointers are fun. Yeah right!";char str2[30], *p1, *p2;
p1 = str1 + strlen(str1) - 1;p2 = str2;
while(p1 >= str1) *p2++ = *p1--;*p2 = '\0';
Pointers and Multi-Dimensional Arrays
•
•
•
•
•
arr[2] is the pointer to the third row
So, we can access arr[2][1] as *(arr[2]+1)
But arr[2] is again same as *(arr + 2)
So, arr[2][1] is same as *(*(arr+2)+1)
In general, arr[i][j] is same as *(*(arr+i)+j)
Dynamic Memory Allocation
•
•
int arr[1000];- sets aside 1000*sizeof(int) bytes of memory irrespective of whether you use it or not
Instead, use malloc() to allocate memory atruntime depending on requirement
And then when you are done using it, use
free() to deallocate itmalloc’ed memory will not be automaticallyfreed until process exits
•
•
malloc()
•
•
int *p = (int *)malloc(sizeof(int)*N)--
-
-
allocates enough memory to hold N int values
returns the starting address of the memory block
we store the address in the pointer pmalloc() returns NULL if memory could not be
allocatedWe can use *p, *(p+1), ..., *(p+N-1) to refer to
the integers in the memory block
•
•
But, *(p+i) is same as p[i]
Effectively, we just dynamically allocated an arrayto hold N integers
free()
• free(p)
-
-
deallocates the memory addressed by p
It’s good practice to set the pointer to NULL: p=NULL
Dynamic Memory for 2D Arrays
•Recall that each row of a 2D array can bereferenced by a pointer to a 1D array• So for 2D arrays, we need a 1D array of pointers
int **p;
p = (int **) malloc(Nrow * sizeof(int *))We just allocated memory to hold Nrow pointers,•
accessed as *(p+i) (or p[i])
for (i=0; i<Nrow; i++)p[i] = (int *)malloc(Ncol * sizeof(int))
•Each of those pointers now points to a block ofmemory of size (Ncol*sizeof(int))
Dynamic Memory for 2D Arrays
•
•
To access the integer at row I and column j, use- *(*(p+i)+j) or p[i][j]
Each *(p+i) need not point to a memory block of samesize
- therefore, each column of the array can be of differentsize
•
•
Tofree the memory:for (i=0; i<Nrow; i++) free(p[i]);
free(**p); p=NULL;
You may also free only certain columns:
free(p[2]); p[2]=NULL;
malloc() example
#include <stdio.h>
#include <stdlib.h>
int main()
int n, i, *ptr, sum=0;
prinm("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)malloc(n*sizeof(int));
if(ptr==NULL)
// number of elements entered by user
//memory allocated using malloc
prinm("Error! memory not allocated.");
exit(0);
prinm("Enter elements of array: ");
for(i=0;i<n;++i) //
//
array values entered by userscanf("%d",ptr+i);
sum+=*(ptr+i);
prinm("Sum=%d",sum);
free(ptr); don’t forgetfree()!
return 0;
Valgrind• Valgrind is a program that is useful for tracking
memory errors (such as segmentation faults) and memory leaks.
• If working on your own machine you may have to install valgrind using: sudo apt install valgrind
• You may run Valgrind with any of your C programs with the following:
valgrind --leak-check=yes ./<executable name>
• If you want to see the line numbers where memory was allocated you must compile with the –g flag.
Ex. gcc –o test –g test.c
Valgrind ExampleBelow is a simple C program to demonstrate valgrind. I ran the program twice with valgrind and included the valgrind output in later slides.
// header files#include <stdio.h>#include <stdlib.h>// main functionsint main()
// give memory leak example// allocate an array of 10 integersint *numPtr = malloc(sizeof(int)*10);int temp = numPtr[1]; // access one value in the arrayfree(numPtr); // free memoryreturn 0;
Valgrind Example Cont.Below are the results of running valgrind with the program when memory is properly freed and accessed. ==3447== Memcheck, a memory error detector==3447== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.==3447== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info==3447== Command: ./valTest==3447== ==3447== ==3447== HEAP SUMMARY:==3447== in use at exit: 0 bytes in 0 blocks ==3447== total heap usage: 1 allocs, 1 frees, 40 bytes allocated==3447== ==3447== All heap blocks were freed -- no leaks are possible==3447== ==3447== For counts of detected and suppressed errors, rerun with: -v==3447== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Notice there is no memory in use at exit
Notice the number of allocsis equal to number of frees
Valgrind Example Cont.Below are the results of running valgrind when memory is not freed and is accessed out of bounds. I removed some unnecessary output from valgrind to save space.
==3518== Invalid read of size 4==3518== at 0x108664: main (valTest.c:11)==3518== Address 0x521c1d0 is 288 bytes inside an unallocated block of size 4,194,096 in arena "client"==3518== ==3518== ==3518== HEAP SUMMARY:==3518== in use at exit: 40 bytes in 1 blocks==3518== total heap usage: 1 allocs, 0 frees, 40 bytes allocated==3518== ==3518== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1==3518== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)==3518== by 0x10865B: main (valTest.c:10)
Accessing an array out of bounds – line 11
Notice there is still memory in use at exit and the number of allocs does not equal number of frees
There was a memory leak of 40 bytes in one block. Allocated on line 10.
Valgrind Example Cont.Below is a continuation of the last slide. Valgrind provides a summary of memory leaks.
==3518== LEAK SUMMARY:==3518== definitely lost: 40 bytes in 1 blocks==3518== indirectly lost: 0 bytes in 0 blocks==3518== possibly lost: 0 bytes in 0 blocks==3518== still reachable: 0 bytes in 0 blocks==3518== suppressed: 0 bytes in 0 blocks
Makefile basics
• A makefile is simply a way of associating short
names, called targets, with a series of
commands to execute when the action is
requested
-
-
Default target: make
Alternate target: make clean
Makefile
••
Basic macro: CC=gcc
Convert a macro to its value in a target: $(CC)- Ex: $(CC) a_source_file.c gets expanded to gcca_source_file.c
• Basic makefile:CC = gcc
FILES = in_one.c in_two.cOUT_EXE = out_executablebuild: $(FILES)
$(CC) -o $(OUT_EXE) $(FILES)
• To execute: make build
Make clean
CC = gccFILES = in_one.c in_two.c
OUT_EXE = out_executablebuild: $(FILES)
$(CC) -o $(OUT_EXE) $(FILES)
clean:rm -f *.o $(OUT_EXE)
•The target make clean will remove all .o filesand the executable
References
•
•
•
•
A Tutorial on Pointers And Arrays in C:
http://home.netcom.com/~tjensen/ptr/pointers.htm
Essential C:
http://cslibrary.stanford.edu/101/EssentialC.pdf
Reading C Type Declarations:
http://unixwiz.net/techtips/reading-cdecl.html
C Programming Dynamic Memory Allocation
http://www.programiz.com/c-programming/c-dynamic-memory-
allocation
• Makefiles
http://www.cprogramming.com/tutorial/makefiles.html