Dynamic memory management (2)

4. Classic written test questions

4.1 Question 1:

void GetMemory(char* p)
{
	p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
}

What will be the result of running the Test function?

The first question: The parameter passed is a pointer, and then malloc is used in the GetMemory function to open up a 100-byte space, and the starting address of this space is assigned Given p, p is a temporary variable that will no longer exist after exiting this function. This space cannot be found, so str is still NULL, so dereferences NULL a>.

Second question: If this space is not freed after use, memory leaks will occur.

Modification: Use the address of str as a parameter, receive it with a secondary pointer, and dereference to find the address of str, so that space can be opened for str. After use, just release it with free and set it to a null pointer.

void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
}

4.2 Question 2:

char* GetMemory(void)
{
	char p[] = "hello world";
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

What will be the result of running the Test function?

p is a temporary variable, which will be destroyed when exiting the function. The address of p is returned to str. The address is returned, but the content inside does not exist, so str is a wild pointer when printed. This is a question of returning the stack space address. Local variables all open space on the stack and are destroyed when they exit the function. If the return address is returned, they will become wild pointers, and this space no longer belongs to p.

4.3 Question 3:

void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}

What will be the result of running the Test function?

There is actually no big problem with this code. The only problem is that there is no free release and there is a memory leak.

Modification: perform free release after printf, and then set str to NULL.

4.4 Question 4:

void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

What will be the result of running the Test function?

First, open up 100 bytes of space for str, then copy the string "hello", and then release it. free just returns this space to the operating system, but the pointer variable is still at this address, so if is still true, but this str is a wild pointer, and an error occurs when using strcpy, which illegally accesses the memory.


5. Memory allocation for C/C++ programs

Local variables and formal parameters open up space in the stack area. Malloc, realloc, and calloc open up space in the heap area. The data segment is also the static area. The data in the code segment cannot be modified, otherwise the code will cause errors, so constants are Put it in this area.

 Several areas of C/C++ program memory allocation:

1. Stack area (stack): When executing a function, the storage units of local variables within the function can be created on the stack, and these storage units are automatically released when the function ends. The stack memory allocation operation is built into the processor's instruction set and is very efficient, but the allocated memory capacity is limited. The stack area mainly stores local variables, function parameters, return data, return addresses, etc. allocated for running functions.
2. Heap area (heap): Generally allocated and released by the programmer. If the programmer does not release it, it may be recycled by the OS when the program ends. The allocation method is similar to a linked list.
3. The data segment (static area) stores global variables and static data. It is released by the system after the program ends.
4. Code segment: stores the binary code of the function body (class member function and global function).

With these words, we can better understand the examples of local variables modified by the static keyword.

In fact, ordinary local variables allocate space in the stack area. The characteristic of the stack area is that the variables created above are destroyed when they go out of scope.
However, variables modified by static are stored in the data segment (static area). The characteristic of the data segment is that the variables created above are not destroyed until the end of the program.
So The life cycle becomes longer.


6. Flexible array

In C99, the last element in the structure is allowed to be an array of unknown size. This is called a "flexible array" member.
For example:

typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
}type_a;

Some compilers will report an error and cannot compile. You can change it to:

typedef struct st_type
{
	int i;
	int a[];//柔性数组成员
}type_a;

 6.1 Characteristics of flexible arrays:

A flexible array member in a structure must be preceded by at least one other member.
The size of this structure returned by sizeof does not include the memory of the flex array.
The structure containing flexible array members uses the malloc () function to dynamically allocate memory, and the allocated memory should be larger than the size of the structure to accommodate the expected size of the flexible array.

 For example:

Normally c occupies 1 byte, i occupies 4 bytes, and according to the structure memory alignment, 3 bytes are wasted, which is equivalent to occupying 8 bytes, so the size of this structure is at least It’s 8. So what’s the answer?

struct S
{
	char c;//1
	//浪费3个字节
	int i;//4
	int arr[];
};
int main()
{
	printf("%d\n", sizeof(struct S));
	return 0;
}

The answer is 8, which is the characteristic of flexible arrays.The size of the structure returned by sizeof does not include the memory of the flexible array.

When a structure with a flexible array member opens up memory space, additional space must be allocated to accommodate the size of the flexible array. For example, the following code uses malloc to open up space and adds 20 bytes at the end. These 20 bytes are reserved for the flexible array arr. When accessed through arr, the following 20 bytes are accessed. When realloc is used to increase space, it is added after these 20 bytes, which is the space added to arr. However, the flexible array must be in a structure and malloc must be used to open up space to be effective.

struct S
{
	char c;//1
	//浪费3个字节
	int i;//4
	int arr[];
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
	if (ps = NULL)
	{
		perror("malloc");
		return 1;
	}
	printf("%d\n", sizeof(struct S));
	return 0;
}

 6.2 Use of flexible arrays

20 bytes are 5 integers, so we can put in 5 integers and release them free after using this space.

struct S
{
	char c;//1
	int i;//4
	int arr[];
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	ps->c = 'w';
	ps->i = 100;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;
	}
	//打印
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	free(ps);
	ps = NULL;
	return 0;
}

If you feel that the space is not enough, use realloc to expand the capacity. The first parameter ps is the starting address of the space that needs to be expanded, followed by 40, which is equivalent to expanding the capacity by 20 bytes. If the capacity expansion is successful, assign ptr to ps. .

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	ps->c = 'w';
	ps->i = 100;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->arr[i] = i;
	}
	//打印
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	struct S* ptr=(struct S*)realloc(ps,sizeof(struct S) + 40);
	if (ptr != NULL)
	{
		ps = ptr;
	}
	else 
	{
		prrror("realloc");
		return 1;
	}
	free(ps);
	ps = NULL;
	return 0;
}

 6.3 Advantages of flexible arrays

Flexible arrays can of course be replaced by other methods. For example, we can use a pointer to point to a space, and then use malloc to open up memory for this space. It should be noted that malloc is used twice to open up space, but how to free it? The space pointed to by data must be freed first, because if the space of the structure is released first, this space includes the space of data, and the space of data cannot be found, so The data space must be released first.

struct S
{
	char c;//1
	int i;//4
	int* data;
};
int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S));
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	ps->c = 'w';
	ps->i = 100;
	ps->data = (int*)malloc(20);
	if (ps->data == NULL)
	{
		perror("malloc");
		return 1;
	}
	for (int i = 0; i < 5; i++)
	{
		ps->data[i] = i;
	}
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", ps->data[i]);
	}
	int* ptr=(int*)realloc(ps->data,40);
	if (ptr != NULL)
	{
		ps->data = ptr;
	}
	else 
	{
		prrror("realloc");
		return 1;
	}
	free(ps->data);
	ps->data = NULL;
	free(ps);
	ps = NULL;
	return 0;
}

Although both methods can achieve the same effect, they have their own advantages and disadvantages.

A flexible array has two benefits:

The first benefit is: convenient memory release

If our code is in a function for others to use, you make a secondary memory allocation in it and return the entire structure to the user. The user can release the structure by calling free, but the user does not know that the members in the structure also need to be free, so you cannot expect the user to discover this. Therefore, if we allocate the memory of the structure and the memory required by its members at once, and return a structure pointer to the user, the user can free all the memory once.

The second benefit is: This is beneficial to access speed

Contiguous memory is beneficial to improving access speed and reducing memory fragmentation. (Actually, I personally don’t think it’s much higher. Anyway, you can’t run and you have to use offset addition to address)


Today’s sharing ends here! Thanks for reading, folks, and see you in the next issue.

Guess you like

Origin blog.csdn.net/2301_79035870/article/details/133996723