Presentation 15100 Content Document 20240115074329PM

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 21

CPPS - Unit 5

1
Dynamic Memory
Memory Allocation in C Programs
• Global Variables in C programs
• These are visible to all the functions in a C program. The required memory space for these variables is
allocated by the compiler/Operating System before the program execution begins.
• The space allocated for these variables are released only when the program ends.
• This type of allocation is called static memory allocation.
• Local variables in C program
• These variables are visible only within the function (or basic block) within which they are declared and
any nested blocks inside them.
• Space for local variables is allocated just when the function is invoked in a region of memory called the
stack. Memory is freed when the function returns.
• Size allocated is based on the number of local variables declared.
• Modern C language allows variable length arrays where the length of the array can be determined at
run-time.
• There is no way to free the allocated memory till the end of the function.
• Both these types of memory allocation are called static memory allocation.
Dynamic Memory allocation – Why do we
need it?
• There are many real world situations where it will be convenient to allocate
the amount of memory needed based on user input and also be able to
release the same after the program has finished some set of operations.
• In static allocation, memory is allocated to the program by the Operating
system and is locked and not available for use by other programs running on
the system.
• It is not always possible to determine the amount of memory needed apriori
and allocate appropriately.
• If we allocate a lesser amount, it becomes cumbersome to handle more data than the
allocated amount.
• If we allocate a much larger amount, we are wasting memory that could have been
otherwise used by other programs.
Dynamic Memory - Basics
• There is a chunk (a certain amount) of memory that is managed by a library
component that provides calls to allocate and free the desired size blocks from
the same.
• This chunk of memory is generally called as ‘Heap Memory’.
• The library makes the required calls to the Operating System to allocate and free
the heap memory as needed (All the memory in a computer is managed by the
Operating System).
• Once it gets a large chunk of memory from the Operating system it may use
optimal algorithms to allocate and free smaller portions from it as the program
requests using the malloc() and free() calls.
• Most real world programs make use of dynamic memory calls to allocate and free
memory as needed.
Basic calls for Dynamic memory
management
• void *malloc(size_t size)
• This is the basic call to allocate a memory block of ‘size’ bytes.
• The call returns a ‘void *’ pointer which can be cast to the appropriate data type
and utilized
• Need to always check if the malloc() call is successful in allocating the size required.
• If malloc() cannot allocate the required memory, it will return ‘NULL’ which can be used to
understand the failure and handle it appropriately.
• void free(void *ptr)
• free() frees the chunk of memory that is pointed to by ‘ptr’. It is important to make
sure that ‘ptr’ is a value returned by a previous call to ‘malloc()’.
• Behaviour is undefined and can cause errors if ‘ptr’ is not a value that was returned
earlier by ‘malloc()’.
Additional calls
• void *calloc(size_t nmemb, size_t size)
• This allocates space for ‘nmemb’ items of size ‘size’.
• Additionally, this call also ensures that the allocated memory is initialized to the value 0
(binary 0x0).
• Memory allocated by ‘calloc()’ is also freed using ‘free()’
• void *realloc(void *ptr, size_t size)
• This is used to either expand or reduce the amount of memory allocated by a previous
call to malloc() or calloc().
• ‘ptr’ should be a value allocated by one of the previous allocation calls.
• ‘size’ is the new size that is desired.
• The returned pointer points to a chunk of memory which is of the new size. If the
memory contents have to be moved, the returned pointer may be different than the
‘ptr’ value passed as the first parameter.
Using Dynamic memory
#include <stdio.h>
#include <stdlib.h> /* We need to include this header for using the
malloc(), free() calls */
{
char *cp; /* pointer to a character (array) */
cp = (char *) malloc( (size_t) (100 * sizeof(char)); /* allocate space for 100
chars */
if(cp == NULL) {
printf(“malloc() failed\n”);
exit(-1);
}
*cp = ‘H’;
*(cp+1) = ‘E’;
*(cp+2) = ‘\0’; /* null termination */
printf(“%s”,cp);

free(cp);
}
More examples..
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

struct student {

char name[50];

int roll_no;

};

int main() {

struct student *s;

s = (struct student *) malloc(sizeof(struct student));

if (s != NULL) {

strcpy(s->name,"John");

s->roll_no = 101;

printf("Student name=%s\n",s->name);

printf("Student roll_no=%d\n",s->roll_no);

else {

printf("malloc() failed\n");

exit(-1);

free(s);
File Operations
What are files?
• A file is an abstraction provided by the Operating System to store
information, typically on a permanent storage device like a hard disk
and be able to retrieve the same later.
• From a programmer’s perspective, a ‘file’ is just a stream of bytes.
• Need to get access to read or write to a file by using some calls to
‘open’ a file.
• Once the task is done, we need to delink the file from the program by
using the ‘close’ call.
• Text files can be read and written using a few simple calls.
Opening a file – fopen()
• We need to first get a handle or a pointer to a file before we can read or
write to it.
• This is done using the ‘fopen()’ call.
FILE *fopen(const char *pathname, const char *mode)
• ‘pathname’ points to the name of the file with the full path. If just the file name
is given, the current directory is assumed.
• ‘mode’ is a string that has specific characters that indicate whether the file is to
be opened for reading, writing, appending etc.
• “r”, “r+”, “w”, “w+”, “a”, “a+” – Please refer to this link for details of the effect of these flags:
https://man7.org/linux/man-pages/man3/fopen.3.html
• The call returns a pointer to a type ‘FILE’, which needs to be used for subsequent
calls to read and write to a file.
Writing to a text file
• int fputc(int c, FILE *stream)
• fputc() is used to write single character stored in ‘c’ to the file pointed to by
‘stream’.
• ‘stream’ should be initialized by using the fopen() call to open the file.
• int fputs(const char *s, FILE *stream)
• fputs() is used to write a string pointed to by ‘s’ to the file pointed by ‘stream’.
• The string ‘s’ should be null terminated – But the null character will not be
written to the file.
Reading from a text file
• int fgetc(FILE *stream)
• fgetc() reads the next character from stream and returns it as an un‐
signed char cast to an int, or EOF on end of file or error.
• ‘stream’ should be initialized by using the fopen() call.
• char *fgets(char *s, int size, FILE *stream)
• fgets() reads in at most one less than size characters from stream and
stores them into the buffer pointed to by s.
• Reading stops after an EOF or a newline. If a newline is read, it is stored
into the buffer.
• A terminating null byte ('\0') is stored after the last character in the buffer.
Closing a file – fclose()
• After finishing the task of either reading/writing to the file, it is good
practice to close the file – this detaches the file from the program and
the Operating system ensures that all the contents are properly saved
on to the permanent medium like hard disk.
• Typically, at the end the program, this happens automatically even if
there is no call to fclose()
• int fclose(FILE *stream)
• The fclose() function flushes the stream pointed to by stream (writing any
buffered output data using fflush(3)) and closes the underlying file
descriptor.
Example – Open/create a file and write 2 lines
#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *fp;
char buf[100];

fp = fopen("a10a11.txt","w"); /* Open for writing at the start, file


is created if it does not exist */
if(fp == NULL) {
printf("fopen failed\n");
exit(-1);
}
fputs("This is the first line\n",fp);
fputs("This is the second line\n",fp);
fclose(fp);
}
Example – Open a file and append 2 lines
#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *fp;
char buf[100];

fp = fopen("a10a11.txt","a"); /* Open for appending, writes go to the end of


the
existing file */
if(fp == NULL) {
printf("fopen failed\n");
exit(-1);
}
fputs("This is the third line\n",fp);
fputs("This is the fourth line\n",fp);
fclose(fp);
}
Example – Open/create file and write 26 characters
#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *fp;
fp = fopen("alpha.txt","a"); /* Open file for appending */
if(fp == NULL) {
printf("fopen failed\n");
exit(-1);
}
char c = 'A’; /* Write 26 characters to the file.. A to Z… */
for(int i=0;i<26;i++)
{
fputc((int) c, fp);
c++;
}
fputc((int) '\n',fp);
fclose(fp);
}
Example – Reading a file – 1 line at a time
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char buf[100];
char *retval;
fp = fopen("a10a11.txt","r");
if(fp == NULL) {
printf("fopen failed\n");
exit(-1);
}
while((retval = fgets(buf,100,fp)) != NULL) {
printf("%s",buf);
}
fclose(fp);
}
Reading a file – 1 character at a time
#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE *fp;
char buf[100];
int c1;

fp = fopen("a10a11.txt","r");
if(fp == NULL) {
printf("fopen failed\n");
exit(-1);
}

while((c1 = fgetc(fp)) != EOF) {


printf("%c",c1);
}
fclose(fp);
}
End of Unit-5

You might also like