Various situations of C++ memory leak/memory out of bounds, as well as prevention and investigation

Table of contents

1. Memory leak

1. Introduction

Two, several memory leak scenarios

3. Prevention and investigation

1、election gate

Two, memory out of bounds

1. Introduction

Two, several cases of memory out of bounds

3. Prevention and investigation


1. Memory leak

1. Introduction

  • A memory leak refers to the memory that is dynamically applied in the program code, and the memory on the heap is not released after use for some reason, resulting in a waste of memory.
  • A small amount of memory leaks will not affect the normal operation of the program, but if it is a continuous memory leak, the system memory will be exhausted, and eventually the program will freeze or even the system will crash. In order to avoid a system crash, when the memory cannot be applied, the exit() function must be called decisively to actively kill the process instead of trying to save the process.

Two, several memory leak scenarios

1. The memory requested by malloc/new is not actively released

void test1()
{
	char* str = new char[100];
	
	/*delete[] str; 这里忘记delete了 */
}

2. New and free are mixed, malloc and delete are mixed

class Base
{
public:
	int* values;
	Base() { values = new int[100]; }
	~Base() { delete[] values; }
};

void test2()
{
	Base* pBase = new Base;

	free(pBase);	
	/* 错误,这样只会释放pBase指向的内存,却不会调用Base的析构函数
	 会导致Base中的values指向的内存无法被释放 */

	delete pBase;	/* 正确 */
}

3. When using new to create an array, delete forgets to add []

void test3()
{
	int* vects = new int[100];

	delete vects;	// 这种写法是错误的
	delete[] vects;	// 这种写法是正确的
}

4. The destructor of the base class is not defined as a virtual function

class A
{
public:
	A() {}
	~A() {}
};

class B : public A
{
public:
	B() { num = new int[100]; }
	~B() { delete[] num; }
private:
	int* num;
};

void main() {
	A* pa = new B();

	delete pa;
	/* 这样只会调用A类的析构函数,而B类中的num就得不到释放
	正确的是应该把A的析构类声明为虚函数 */
}

3. Prevention and investigation

1、election gate

  • Application environment: Linux
  • Programming language: C/C++
  • How to use: Add the -g option when compiling, such as gcc -g filename.c -o filename, and use the following command to check the memory usage:
  • Result output: #valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./filename, you will see the memory usage report
  • Design idea: maintain a valid address space table and an invalid address space table (the address space of the process) according to the memory operation of the software
  • Pros and Cons: Ability to detect:
    • Use of uninitialized memory
    • Use memory that has been freed (Reading/writing memory after it has been free'd)
    • Using more than malloc allocated memory space (Reading/writing off the end of malloc'd blocks)
    • Illegal access to the stack (Reading/writing inappropriate areas on the stack)
    • Whether the requested space has been released (Memory leaks – where pointers to malloc'd blocks are lost forever)
    • malloc/free/new/delete application and release memory matching (Mismatched use of malloc/new/new [] vs free/delete/delete [])
    • Overlapping src and dst pointers in memcpy() and related functions
    • repeat free
  • How to get it: http://valgrind.org/

2. Use smart pointers

void test4()
{
	// 以下两种写法效果相同
	shared_ptr<int> p1 = shared_ptr<int>(new int(234));
	shared_ptr<int> p2 = make_shared<int>(234);

	// 还有其他指针指针
	weak_ptr<int>   p3 = weak_ptr<int>(p1);
	unique_ptr<int> p4 = unique_ptr<int>(new int(234));
	auto_ptr<int>   p5 = auto_ptr<int>(new int(234));
}

Two, memory out of bounds

1. Introduction

  • Memory out of bounds is one of the main errors in software systems, and its consequences are often unpredictable and very serious. What's more troublesome is that the timing of its appearance is random, the symptoms it exhibits are random, and the consequences are also random, which makes it difficult for programmers to find out the connection between the phenomenon and the essence of these bugs, so that It brings great difficulty to locate the bug. In general, memory out-of-bounds access can be divided into the following two types:
  • Reading out of bounds means reading data that does not belong to you. If the read memory address is invalid, the program crashes immediately; if the read memory address is valid, there will be no immediate problem when reading, but because the read data is random, it will cause unpredictable consequences .
  • Writing out of bounds, also known as buffer overflow, the written data is random for other programs, and it will also cause unpredictable consequences.

Two, several cases of memory out of bounds

  1. When the pointer is defined, it is not initialized, so the pointer points to a random value, and the user does not necessarily have access rights.
  2. The allocated memory is less than the actual used memory.
  3. Wrong subscript when using subscript to access array.
  4. The memory has been freed, but pointers are still used to use this memory.

3. Prevention and investigation

  1. When defining a pointer variable, if you don't initialize it temporarily, you can let it point to nullptr first.
  2. When allocating memory, the user should check whether the memory is allocated successfully.
  3. When using a subscript to access an array, check whether it is out of bounds.
  4. After the memory is freed, the pointer pointing to this memory should also be assigned a value of nullptr.

Guess you like

Origin blog.csdn.net/iuu77/article/details/129843314