Dynamic memory management, file operation, preprocessing

Last

Dynamic memory management

Apply for memory by creating variables When memory is released depends on what kind of variable the variable is
If it is a global variable, it will be released following the program
If it is a static variable, it is also released with the program
If it is a local variable, it is released following the code block

1. Dynamic memory management can more flexibly determine the application time and release time~
2. Dynamic memory management can determine the size of memory application at run time~

malloc

void* malloc (size_t size);
//size is the number of bytes. The compiler only knows the starting address of memory,
//Do not know the size, apply for continuous memory,
//Under normal circumstances, check whether the application is successful (NULL if unsuccessful)

use

#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
int main(){
	int* p = (int*)malloc(4);
	*p = 10;
	printf("%d\n", *p);

	 //Understand these 40 bytes as an int array with a length of 10 elements
	// p is the starting element address of the array 
	int* p = (int*)malloc(10 * sizeof(int));

	for (int i = 0; i < 10; i++) {
		p[i] = 0;
	}
	system("pause");
	return 0;
}

Release time

1. If the program finishes running, it will be released together with the program
2. When the program is not finished, call free manually, and it will be released

free

void free (void* ptr);//The address returned by ptr maolloc can handle NULL

use

#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
int main(){
	 //Understand these 40 bytes as an int array with a length of 10 elements
	// p is the starting element address of the array 
	int* p = (int*)malloc(10 * sizeof(int));

	for (int i = 0; i < 10; i++) {
		p[i] = 0;
	}
	free(p);
	system("pause");
	return 0;
}

The introduction of "smart pointer" in C + + can solve the problem of memory leakage to a certain extent. Using the RAlI mechanism ~ in C + + can execute some logic before the function exits
You can put the free operation into such logic~
Java / Python, with the introduction of garbage collection mechanism, can better solve the problem of memory leakage
Memory recycling does not need to be manually recycled by the program, but there is special logic inside the program to scan regularly to see which memory can be released at present, and then it will be released automatically

calloc

void* calloc (size_t num, size_t size);

use

#include <stdio.h>
#include <stdlib.h>
int main()
{
 int *p = (int*)calloc(10, sizeof(int));
 if(NULL != p)
 {
 //Use space
 }
 free(p);
 p = NULL;
 return 0; }

The memory requested by calloc will be initialized to all 0
The memory requested by malloc will not be initialized, and the values in memory are random values

realloc

When realloc expands, it also depends on whether there is enough free space in the back. If there is enough space in the back, you can directly break through the wall and make direct use of the space in the back
If there is not enough space in the back, just find a larger space and move it as a whole~

void* realloc (void* ptr, size_t size);

use

#include <stdio.h>
int main()
{
 int *ptr = (int*)malloc(100);
 if(ptr != NULL)
 {
     //Business processing
 }
 else
 {
     exit(EXIT_FAILURE);    
 }
 //Expansion capacity
 //Code 1
 ptr = (int*)realloc(ptr, 1000);//Is this ok? (what happens if the application fails?)
 
 //Code 2
 int*p = NULL;
 p = realloc(ptr, 1000);
 if(p != NULL)
 {
 ptr = p;
 }
 //Business processing
 free(ptr);
 return 0; }

Common memory errors

void test()
{
 int *p = (int *)malloc(INT_MAX/4);
 *p = 20;//If the value of p is NULL, there is a problem
 free(p);
}

void test()
{
 int i = 0;
 int *p = (int *)malloc(10*sizeof(int));
 if(NULL == p)
 {
 exit(EXIT_FAILURE);
 }
 for(i=0; i<=10; i++)
 {
 *(p+i) = i;//Cross border access when i is 10
 }
 free(p);
}

void test()
{
 int a = 10;
 int *p = &a;
 free(p);//Only dynamically requested memory is released
}

void test()
{
 int *p = (int *)malloc(100);
 p++;
 free(p);//p no longer points to the beginning of dynamic memory
}

void test()
{
 int *p = (int *)malloc(100);
 free(p);
 free(p);//Repeated release
}

void test()
{
 int *p = (int *)malloc(100);
 if(NULL != p)
 {
 *p = 20;
 }//Memory leak
}
int main()
{
 test();
 while(1);
}

Common question types

1.

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

1. Memory leak malloc has no free
2. It is not determined that the return value is NULL after malloc
3. The getmemory function cannot modify the value of str. ~ STR is still NULL After strcpy, there will be a problem~

2.

char *GetMemory(void) {
 char p[] = "hello world";//Local variables are released as the function is released
 return p; }
void Test(void) {
 char *str = NULL;
 str = GetMemory();//The memory referred to by the local variable has been released
 printf(str);
}

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);
}

1. Memory leak malloc has no free
2. It is not determined that the return value is NULL after malloc

4.

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

The memory area of a program

In linux


Stack size can be configured (generally 1m)

linux modifies the stack size

file

classification

Ordinary file: text file, binary file
Catalog file

correlation function

All io functions are in stdio Included in H

FILE structure

Used to describe a file~
The file is on disk It's not easy to operate the disk directly Therefore, the operating system is encapsulated
When you open a FILE, you actually create a variable (FILE structure variable) in memory, which is associated with the FILE on the disk Reading / writing this variable is equivalent to reading and writing files

fopen

//Open file
FILE * fopen ( const char * filename, const char * mode );
//Parameter the file path of the former and the opening method of the latter

use

#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(){
	/* fp => file pointer field name pointer
		 NULL is returned if opening the file fails If the file does not exist or does not have read and write permissions, it will fail*/ 
		FILE* fp = fopen("E:/test.txt", "r");
		if (fp == NULL) {
			printf("fail to open file! Error code: %s\n", strerror(errno));//Error a macro definition represents an error
			system("pause");
			return 0;
		}
		printf("File opened successfully! fp=%p\n", fp);
	system("pause");
	return 0;
}

strerror

Return the error code and the corresponding error information.

char * strerror ( int errnum );

use

#include <stdio.h>
#include <string.h>
#include <errno. h> / / header files that must be included
int main ()
{
  FILE * pFile;
  pFile = fopen ("unexist.ent","r");
  if (pFile == NULL)
    printf ("Error opening file unexist.ent: %s\n",strerror(errno));
    //errno: Last error number
  return 0; }

fclose

//Close file
int fclose ( FILE * stream );

use

#include <stdio.h>
int main ()
{
  FILE * pFile;
  //Open file
  pFile = fopen ("myfile.txt","w");
  //File operation
  if (pFile!=NULL)
 {
    fputs ("fopen example",pFile);
    //Close file
    fclose (pFile);
 }
  return 0; }

fread

Data reading mode: byte stream and datagram

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
//*ptr reads the memory address of the content and returns the number of successful reads

use

#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(){
	/* fp => file pointer field name pointer
		 NULL is returned if opening the file fails If the file does not exist or does not have read and write permissions, it will fail*/ 
		FILE* fp = fopen("E:/test.txt", "r");
		if (fp == NULL) {
			printf("fail to open file! Error code: %s\n", strerror(errno));//Error a macro definition represents an error
			system("pause");
			return 0;
		}
		printf("File opened successfully! fp=%p\n", fp);
		char buffer[10] = "1111" ;
		fread(buffer, 1, 8, fp);
		printf(buffer);
	system("pause");
	return 0;
}

fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

use

#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(){
	/* fp => file pointer field name pointer
		 NULL is returned if opening the file fails If the file does not exist or does not have read and write permissions, it will fail*/ 
		FILE* fp = fopen("E:/test.txt", "w");
		if (fp == NULL) {
			printf("fail to open file! Error code: %s\n", strerror(errno));//Error a macro definition represents an error
			system("pause");
			return 0;
		}
		printf("File opened successfully! fp=%p\n", fp);
		char buffer[10] = "1111" ;
		fwrite(buffer, 1, 4, fp);
		printf(buffer);
	system("pause");
	return 0;
}

Other sequential reading and writing

EOF
If a file has been read, and then continue to try to read, EOF will be read
EOF 'is actually - 1, not a character in ascii code table Just use - 1 to represent that the file has been read

sscanf and sprintf

//sscanf parses a content from a string
//sprintf outputs a formatted result to a string
	char* str = "num = 10";
	int num = 0;
	sscanf(str, "num = %d", &num);
	printf("%d\n", num);
	char str[1024] = { 0 };
	sprintf(str, "num = %d", 10);
	printf(str);


A particularly important usage://For conversion between strings and numbers (integers / floating point numbers)~
// Convert the string to an integer and use sscanf
		char* str1 = "10";
		char* str2 = "20";
		// Here I want to calculate the sum of these two values~ 

		int num1 = 0;
		// At this time, the content in str1 is extracted and converted into int
		sscanf(str1, "%d", &num1);
		int num2 = 0;
		sscanf(str2, "%d", &num2);
		int result = num1 + num2;
		printf("result = %d\n", result);


// Convert an integer to a string and use sprintf
	int num = 100;
	char buffer[1024] = { 0 };
	sprintf(buffer, "%d", num);
	printf("%s\n", buffer);

Integer and string conversion atoi iota

#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>     /* atoi */

int main ()
{
	int i;
	char buffer[256];
	printf("Enter a number: ");
	fgets(buffer, 256, stdin);
	i = atoi(buffer);
	printf("The value entered is %d. Its double is %d.\n", i, i * 2);
	system("pause");
	return 0;

}



char *  itoa ( int value, char * str, int base );

#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>     /* atoi */

int main ()
{
	int i;
	char buffer[33];
	printf("Enter a number: ");
	scanf("%d", &i);
	_itoa(i, buffer, 10);
	printf("decimal: %s\n", buffer);
	_itoa(i, buffer, 16);
	printf("hexadecimal: %s\n", buffer);
	_itoa(i, buffer, 2);
	printf("binary: %s\n", buffer);
	system("pause");
	return 0;

}

fscanf

int fscanf ( FILE * stream, const char * format, ... );

use

/* fscanf example */
#include <stdio.h>

int main ()
{
  char str [80];
  float f;
  FILE * pFile;

  pFile = fopen ("myfile.txt","w+");
  fprintf (pFile, "%f %s", 3.1416, "PI");
  rewind (pFile);
  fscanf (pFile, "%f", &f);
  fscanf (pFile, "%s", str);
  fclose (pFile);
  printf ("I have read: %f and %s \n",f,str);
  return 0;
}

fprintf

int fprintf ( FILE * stream, const char * format, ... );

use

#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(){
	/* fp => file pointer field name pointer
		 NULL is returned if opening the file fails If the file does not exist or does not have read and write permissions, it will fail*/ 
		FILE* fp = fopen("E:/test.txt", "w");
		if (fp == NULL) {
			printf("fail to open file! Error code: %s\n", strerror(errno));//errno a macro definition represents an error
			system("pause");
			return 0;
		}
		printf("File opened successfully! fp=%p\n", fp);
		char buffer[10] = "1111" ;
		fprintf(fp,"jiezhe:%s",buffer);
		printf(buffer);
	system("pause");
	return 0;
}
// stdout is actually a variable of type FILE * This is what we call standard output 
	// This code is equivalent to printf 
	 fprintf(stdout, "num = %d\n", 10);
	// Similarly, fscanf(stdin, "xxxxx"); This code is equivalent to scanf 

Random reading and writing

fseek

Locate the file pointer according to the position and offset of the file pointer

int fseek ( FILE * stream, long int offset, int origin );

#include <stdio.h>

int main ()
{
  FILE * pFile;
  pFile = fopen ( "example.txt" , "wb" );
  fputs ( "This is an apple." , pFile );
  fseek ( pFile , 9 , SEEK_SET );
  fputs ( " sam" , pFile );
  fclose ( pFile );
  return 0;
}

ftell

Returns the offset of the file pointer from the starting position

long int ftell ( FILE * stream );

#include <stdio.h>
int main ()
{
  FILE * pFile;
  long size;
  pFile = fopen ("myfile.txt","rb");
  if (pFile==NULL) perror ("Error opening file");
  else
 {
    fseek (pFile, 0, SEEK_END);   // non-portable
    size=ftell (pFile);
    fclose (pFile);
    printf ("Size of myfile.txt: %ld bytes.\n",size);
 }
  return 0; }

rewind

Returns the position of the file pointer to the starting position of the file

void rewind ( FILE * stream );


#include <stdio.h>
int main ()
{
  int n;
  FILE * pFile;
  char buffer [27];
  pFile = fopen ("myfile.txt","w+");
  for ( n='A' ; n<='Z' ; n++)
    fputc ( n, pFile);
  rewind (pFile);
  fread (buffer,1,26,pFile);
  fclose (pFile);
  buffer[26]='\0';
  puts (buffer);
  return 0; }

Determination of end of file reading

  1. Whether the text file reading is completed, and judge whether the return value is EOF (fgetc) or NULL (fgets)
    For example:
    fgetc determines whether it is EOF
    fgets determines whether the return value is NULL
  2. Judge whether the return value is less than the actual number to be read after reading the binary file.
    For example:
    fread determines whether the return value is less than the actual number to be read.

Refresh cache

#include <stdio.h>
#include <windows.h>
//VS2013 WIN10 environment test
int main()
{
 FILE*pf = fopen("test.txt", "w");
 fputs("abcdef", pf);//Put the code in the output buffer first
 printf("Sleep for 10 seconds-The data has been written. Open it test.txt File, no content found in the file\n");
 Sleep(10000);
 printf("refresh buffer \n");
 fflush(pf);//When the buffer is refreshed, the data of the output buffer is written to the file (disk)
 //Note: fflush cannot be used on higher version VS
 printf("Sleep for another 10 seconds-At this point, open again test.txt File, the file has content\n");
 Sleep(10000);
 fclose(pf);
 //Note: fclose also flushes the buffer when closing the file
 pf = NULL;
 return 0; }

Cache refresh time:
1. The buffer is full
2. fclose is closed
3. The function of fflush is to manually refresh the buffer

Pretreatment

2 the compilation process is the most important

predefined symbol

__FILE__      //Source file for compilation
__LINE__     //The current line number of the file
__DATE__    //Date the file was compiled
__TIME__    //The time the file was compiled
__STDC__    //If the compiler follows ANSI C, its value is 1, otherwise it is undefined

define

1. Define constants~

#define MAX 1000

2. Define alias for type~

#define uint unsigned int
uint num = 10;

3. Customize some "Keywords"|

#define and &&
	#define and&&
	#define if
	#define else
	#define loop for
	#define assignment=
	#define integer int
	int num = 10;
	if (num < 10 also num > 0) {

	}
	integer num Assignment 10;
	If(num < 10 also num > 0) {

	} otherwise {

	}

4. Use macros as some "compile switches" (combiner #if this series of operations)

5. Define a code fragment

#define ADD(x, y) x + y
printf("%d\n", ADD(10, 20));

Macro advantages and problems



3. Macros are not recursive
4. Macro has no parameter check (it seems convenient not to write the type of the parameter, but it is actually more troublesome. The parameter has not been checked. It is unknown whether your actual parameter is passed correctly and whether it meets the requirements)|

#undef

This instruction is used to remove a macro definition.

Conditional compilation

1.
#if constant expression
 //...
#endif
//Constant expressions are evaluated by the preprocessor.
For example:
#define __DEBUG__ 1
#if __DEBUG__
 //..
#endif
2.Conditional compilation of multiple branches
#if constant expression
 //...
#elif constant expression
 //...
#else
 //...
#endif
3.Determine whether it is defined
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.Nested instruction
#if defined(OS_UNIX)
 #ifdef OPTION1
 unix_version_option1();
 #endif
 #ifdef OPTION2
 unix_version_option2();
 #endif
#elif defined(OS_MSDOS)
 #ifdef OPTION2
 msdos_version_option2();
 #endif
#endif

Application:
1. Compatible with development and release environment,

2. Compatible with multiple systems,
3. Prevent repeated inclusion of header files (#pragma once is used at the definition),
4. Realize multi line annotation, as follows:

5. Support nesting

Keywords: C C++

Added by chaking on Mon, 03 Jan 2022 18:45:10 +0200