当前位置:网站首页>[dynamic memory management] malloc & calloc and realloc and written test questions and flexible array

[dynamic memory management] malloc & calloc and realloc and written test questions and flexible array

2022-06-12 08:28:00 Always brush questions every day

0 Why dynamic memory management exists ?

 

char str[20]={0];
int arr[20]={0};

The above-mentioned way of space development has two characteristics :

  1. The size of space is fixed
  2. When declaring an array, you must specify the size of the array space , It allocates the required memory at compile time

But if the amount of space we need is uncertain at the time of program compilation , It's not until the program runs , Then the above-mentioned way of space development is not suitable , Dynamic memory management came into being .

Define the difference between local variable memory and dynamic memory :

  • Where to open up space :
  • Define the space opened up by local variables : Random position on stack
  • Dynamic application space : Continuous position on the stack
  • Release :
  • Define the space opened up by local variables : Automatic destruction of outgoing code blocks
  • Dynamic application space : It is better for the programmer to release manually

1 malloc function

The function prototype :void* malloc(size_t size)

Parameter description :size For the size of memory space to be allocated , Unit is byte


#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int main()
{
    // The function prototype :void* malloc(size_t size)
	// Applied to memory 40 Bytes of space :
	// If the application is successful, the first address of this space will be returned 
	// If the application fails, a null pointer is returned NULL
	int* p1 = (int*)malloc(40);// The development was successful 
	int* p2 = (int*)malloc(INT_MAX+1);// This development failed 
	// When you use this space later, it will change p The direction of , So use ptr Keep the starting address of this space 
	int* ptr = p1;
	// Check pointer p The effectiveness of the : Check whether the return value of the memory request result is NULL
	if (p· == NULL)
	{
		perror("malloc");//malloc: Not enough space
		exit(-1);
	}
	// Opens the 40 Bytes , That is to say 10 individual int The size of the type variable 
	for (int i = 0; i < 10; i++)
	{
		*(p·++) = 0;
	}
	// Release ptr The space pointed to by the pointer , however ptr The starting address of the space for dynamic application is still reserved 
	free(ptr);
	// Give Way ptr Pointing empty , Make him lose the memory of the starting address of the space dynamically applied for 
	ptr = NULL;

    p=NULL;
	return 0;
}

When we do not manually free the space opened up by dynamic memory :

  • If the program ends , The dynamically requested memory consists of OS Automatic recovery
  • But if the program never ends , The space requested by dynamic memory will not be released automatically , It will cause memory leakage problems . ( The memory of dynamic application will be automatically released after the program ends , Otherwise, the memory will be less and less , Who dares to write code ; But when this space takes up too long , And this space is relatively large , Will compare to eat memory )

2  calloc function

The function prototype :void* calloc(size_t num,size_t  size)

Parameter description :num Is to assign size The number of elements in a space of bytes

 malloc and   calloc The difference between : calloc When applying for memory space, initialize this space to 0 了


int main()
{
	// The function prototype : void* calloc(size_t num,size_t size)
    // Element number :10
    // The number of bytes per element :sizeof(int)
	int* p = (int*)calloc(10, sizeof(int));
	int* ptr = p;
	if (p == NULL)
	{
		perror("calloc");
		exit(-1);
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d\t", *(p++));
	}
	free(ptr);
	ptr = NULL;
	p = NULL;
}

 3 realloc function

With realloc function , We can already malloc or calloc Readjust the space that has been opened up and is not satisfied with the capacity .( adjustment : You can turn it up or down )

Reallocate memory space function :void* realloc(void* ptr,size_t size)

Parameter description :ptr To point to the space that needs to be reallocated ,size For the amount of space that needs to be reallocated , Unit is byte .

Let's take capacity expansion as an example :

int main()
{
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i;//p No change of direction 
	}
	// Hope to put 20 Elements , Space is not enough , Consider using realloc Capacity expansion 
	int p = (int*)realloc(p, 80);//error, In case realloc Expansion failed ,p A null pointer was received , Turn the original p Directional coverage of ( lose ) 了 

	// The function prototype :void* realloc(void* ptr,size_t size)
	//ptr: A pointer , The pointer points to the starting address of the expanded space 
	//size: The number of bytes expected after successful expansion 
	int* temp = (int*)realloc(p, 80);//bingo
	if (temp != NULL)
	{
		p = temp;
	}
	free(p);
	p = NULL;

	return 0;
}

 realloc Adjust the space :

  1. If you want to reduce the space : Then the space of corresponding length is intercepted on the original space , And return the original first address ( It's equal to p)
  2. If it is to expand space , Below 3 In this case :
  • If the location of the original space in the memory can open up the required space after the expansion , We will open up accordingly , And return the starting address of the new space .
  • If the location of the original space in the memory cannot open up the space required after the expansion ,OS You will find a new space in the heap memory that is large enough to hold the required space , Copy the values in the original space to the new space , And return the starting address of the new space
  • If any location in the heap memory is not enough to open up the required memory space , Return null pointer .

4 Common dynamic memory errors


	int main()
	{
		//way1: Yes NULL Pointer to dereference 
		int* p = (int*)malloc(INT_MAX + 1);
		// Use it directly //error

		//way2: A cross-border visit 
		int* p = (int*)malloc(40);
		if (p == NULL)
		{
			perror("malloc");
			exit(-1);
		}
		for (int i = 0; i < 11; i++)//error
		{
			*(p + i) = i;
		}

		//way3: Use free Function to free non dynamically requested memory 
		int a = 10;
		int* p = &a;
		free(p);//error
		p = NULL;


		//way4: Use free Function to free a portion of the dynamically requested memory 
		int* p = (int*)malloc(40);
		if (p == NULL)
		{
			perror("malloc");
			exit(-1);
		}
		for (int i = 0; i < 11; i++)//error
		{
			*p = i;
			p++;
		}
		free(p);//error
		p = NULL;

		//way5: The memory of the same dynamic request is released multiple times 
		free(p);
		free(p);
		p = NULL;


	   //way6: Forget to free the memory of dynamic application 


		return 0;
	}

5 2 A classic written test question :

Pen test 1: The following code can print out hello world Do you ?------> Value and address

// Error code :
void Getmory(char* p)
{
	p = (char*)malloc(100);
}

void test(void)
{
	char* str = NULL;
	Getmory(str);
	strcpy(str, "hello world");
	printf(str);
}

int main()
{
	test();
	return 0;

}

  answer : You can't , According to the original meaning of the code : Want to pass Getmory Function gives str Dynamic development for a period 100 Bytes of space , And then use strcpy Function copies the string ‘hello world’ And print it out .

The problem lies in :Getmory The function parameter of a function is just a character pointer str A temporary copy of , The change of formal parameters p Does not affect arguments str, And in that case ,p The space pointed to is p No code block has been released , Out Getmory After the function code block , local variable p Be destroyed , The space of this dynamic application has not been destroyed , Can no longer be destroyed .

in addition , chain reaction ,str Or point to empty ,strcpy When the function is executed, the source space is insufficient "hello world“

, There will be a second problem .

Correct code :

// Correct code :
void Getmory(char** p)
{
	*p = (char*)malloc(100);
}

void test(void)
{
	char* str = NULL;
	Getmory(&str);
	strcpy(str, "hello world");
	printf(str);
}

int main()
{
	test();
	return 0;

}

 

Pen test 2: The following code can print out "hello world“ Do you ”-------->“ Return stack space address problem ”

// Error code :
char* Getmory(void)
{
	char p[] = "hello world";
	return p;
}

void test()
{
	char* str = NULL;
	str = Getmory();
	printf(str);
}

int main()
{
	test();

	return 0;
}

answer : You can't ,Getmory Function ,"hello world” Is placed in a character array , When returned, the array name is returned , That is, the address of the first element of the array ,Getmory The space occupied by the character array is automatically destroyed at the end of the function , But it returns the address of the stack space , Once in a test Function to access the address dereference , That's illegal , Unknown , The error cause of the above code is similar to that of the following code .

// Error code 
int* test()
{
	int a = 10;
	return &a;
}

int main()
{
	int* p=test();
	*p = 10;
	printf("%d\n", *p);
	printf("%d\n", *p);
	return 0;

}

6  Flexible array

Flexible array : The last element in the structure is allowed to be an array of unknown size , This is the same as 【 Flexible array 】 member .


struct s
{
	int num;
	double e;
	int arr[0];
	// or int arr[0];
};

The characteristics of flexible arrays :

  1. A flexible array member in a structure must be preceded by at least one other non flexible array member .
  2. The memory size of the structure containing the flexible array does not include the memory size of the flexible array .
  3. Structures containing flexible arrays must be used when opening up memory malloc Function dynamic memory development , And the open space must be larger than the size of the structure , To accommodate the expected size of the flexible array .
struct s
{
	int num;
	int arr[0];
	// or int arr[0];
};

int main()
{
	printf("sizeof(struct s):>%d\n", sizeof(struct s));
	struct s* ps = (struct s*)malloc(sizeof(struct s) + 40);

	ps->num = 100;
	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d\t", ps->arr[i]);
	}
	return 0;
}

struct s
{
	int num;
	int arr[0];
	// or int arr[0];
};

int main()
{
	printf("sizeof(struct s):>%d\n", sizeof(struct s));
	struct s* ps = (struct s*)malloc(sizeof(struct s) + 40);
	if (ps == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	ps->num = 100;
	for (int i = 0; i < 10; i++)
	{
		ps->arr[i] = i;
	}

	for (int i = 0; i < 10; i++)
	{
		printf("%d\t", ps->arr[i]);
	}

	// The flexible meaning of flexible array : Sure realloc Capacity expansion 
	struct s* temp = (struct s*)realloc(ps, sizeof(struct s) + 80);
	if (temp != NULL)
	{
		ps = temp;
	}

	for (int i = 0; i < 20; i++)
	{
		ps->arr[i] = i;
	}
	for (int i = 0; i < 20; i++)
	{
		printf("%d\t", ps->arr[i]);
	}
	free(ps);
	ps = NULL;
	return 0;
}

 

 

原网站

版权声明
本文为[Always brush questions every day]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/163/202206120826357904.html