C language - memory function

Posted by Cerberus_26 on Tue, 25 Jan 2022 22:48:09 +0100

Memory function

In C language, when a program is loaded into memory to run, the system will allocate an independent memory space for the program, and this memory space can be subdivided into many areas, such as stack area, heap area, static area, global area, etc

Stack area: save local variables. The variables stored in the stack area will be automatically released by the system after the function is executed.

Heap area: allocate memory by malloc, calloc, realloc... And other functions. Its life cycle is controlled by the free function and exists until the program is run.

Stack memory

The local variables defined inside the function are stored in the stack area. The stack area is characterized by: after the function is executed, the system "automatically reclaims" the memory space corresponding to the local variable. The so-called "automatic recycling" is actually that the operating system allocates this stack memory to local variables in other functions.

When defining a local variable, the system will allocate a memory space for it in the stack area. When the function is executed, the system is responsible for reclaiming this memory and allocating it to other local variables.

After the following code is executed, you will find that the memory addresses of the output a and b variables are the same. It can be explained that the memory corresponding to local variables will be recycled and allocated to local variables in other functions after the function is executed. Therefore, in C language, the address of a local variable cannot be returned as the return value of a function, otherwise problems may occur

#include<stdio.h>

void showA()
{
	int a;
	printf("&a=%p\n",&a);
}

void showB()
{
	int b;
	printf("&b=%p\n",&b);
}

int main(void)
{
	showA();
	showB(); 
	getchar();
	return 0;
}

Stack memory:

(1) Automatically allocated and released by the system. Such as function parameters and local variables.

(2) The stack memory is relatively small. In VS2012, the default maximum stack memory is 1M. If the stack memory occupied by local variables is too large, stack overflow will occur.

#include<stdio.h>
int main(void)
{
int a[9900000];//StackOverflow will be generated
getchar();
return 0;
}

Heap memory

The memory allocated by the malloc series function is all in the heap area. After use, the free function is called to release, otherwise it may cause memory leak (that is, the memory can not be used again).

malloc function
Function prototype: void *malloc(int size);

Header file: #include < stdlib h>

Parameter list: size: how many bytes are allocated.

Function: apply for heap memory of specified size.

Return value: if the allocation is successful, the pointer to the allocated memory is returned; otherwise, the NULL pointer is returned.

Void * refers to the pointer of "uncertain pointing type". Before use, forced type conversion must be carried out to convert void * into the pointer of "certain pointing type".

free function

Function prototype: void free(void* ptr);

Header file: #include < stdlib h>

Parameter list: ptr: points to the heap memory to be freed.

Function: release the memory space pointed by ptr.

In C language, the heap memory after free will be recycled and redistributed by the operating system. It is not recommended to continue to use it, otherwise the output result will be unpredictable.

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
	int *p = (int *)malloc(sizeof(int));//The return value of void * type must be forcibly typed
	*p = 200;
	printf("%p, %d\n", p, *p);//Output the memory address pointed to by pointer p, and output the value in this memory address
	free(p);
	getchar();
	return 0;
}

Heap memory

(1) Application and release by programmers themselves. If it is not released, memory leakage may occur until it is released by the system after the program is completed.

(2) The heap memory is relatively large, and more than 1G of memory space can be allocated.

Function returns data in two ways

  1. malloc is used to allocate memory in the called function, and free is used to release memory in the calling function.
#include<stdio.h>
#include<stdlib.h>

int* getMemory()
{
    int* p_int=(int*)malloc(sizeof(int));//The called function allocates memory for use
    *p_int=100;
    return p_int;
}

int main(void)
{
    int* p=getMemory();
    printf("%d\n",*p);
    free(p); //The calling function releases memory
    getchar();
    return 0;
}

Allocating memory and releasing memory are separate, which can easily lead to programmers forgetting to release memory in the calling function, resulting in memory leakage,

2. Allocate heap memory in the calling function, use heap memory in the called function, and finally release heap memory in the calling function.

#include<stdio.h>
#include<stdlib.h>

void fun(int *p_int)
{
	*p_int=100;
}

int main(void)
{
    int* p=(int*)malloc(sizeof(int)); //The main calling function allocates heap memory
    fun(p);
    printf("%d",*p);
    free(p); //The main calling function releases heap memory
    getchar();
    return 0;
}

This method is recommended

For the heap memory allocated by malloc function, the system will not initialize the memory, and old data will remain in the allocated memory. Therefore, referring to uninitialized heap memory, the output data will also be unknown.

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int *p_int=(int*)malloc(sizeof(int));
printf("%d",*p_int);//Output random unknown data
getchar();
return 0;
}

In order to avoid referencing unknown data in the heap memory, malloc is generally used. After allocating memory in the heap area, this heap memory needs to be initialized to 0

memset

Function prototype: void* memset(void *dest, int c, size_t size);
Header file: #include < string h>
Parameter list: dest: the target memory area to be initialized. c: The character to set. Size: initialize size bytes.
Function: initialize the first size bytes of the memory space pointed to by DeST to c. Return value: the memory address of dest.

#include<stdio.h>
#include<string.h>

int main(void)
{
	char arr[10] = {0};
    //The first five byte elements of arr will be set to@
	memset(arr, '@',5);
	getchar();
	return 0;
}

memcpy

Function prototype: void* memcpy(void* destination, const void* source, size_t num);

The memcpy function copies num bytes of data backward from the position of the source pointer to the memory position pointed to by the destination pointer
However, the num byte data of source and destination cannot overlap in memory, otherwise the replication result is unknown
memcpy can copy any type of data

#include<stdio.h>
#include<string.h>
 
struct S
{
	int age;
	char name[5];
};

int main(void)
{
	struct S arr1[] = {{18,"abc"}, {22, "456"}};
	struct S arr2[3] = {0};
    //It can be seen from the memory that the data of arr1 has been copied to arr2
	memcpy(arr2, arr1, sizeof(arr1));
	getchar();
	return 0;
}

Simple implementation of my_memcpy

void* my_memcpy(void* dest, void* source, size_t num)
{
    assert(dest && source);
	void* res = dest;
	while(num--){
		*(char*)dest = *(char*)source;
		++(char*)dest;
		++(char*)source;
	}
	return res;
}

memmove

Function prototype: void* memmove(void* destination, const void* source, size_t num);

The memmove function copies num bytes of data backward from the position of the source pointer to the memory position pointed to by the destination pointer
However, the data of num bytes of source and destination can overlap in memory

memcmp

Function prototype: int memcmp(void* ptr1, void* prt2, size_t num);

Compare the size of num bytes of data starting from ptr1 pointer and ptr2 pointer

#include<stdio.h>
#include<string.h>

int main(void)
{
	int res = 0;
	char arr1[] = {1,2,3,4,5};
	char arr2[] = {1,2,4,5,5};
    //compare
	res = memcmp(arr2, arr1,3);
	printf("%d", res);
	getchar();
	return 0;
}

Topics: C C++