About how to recycle the class static member variable pointer through the dynamically allocated memory, variable pointer
If a class has a static member variable pointer and the memory is dynamically allocated in the following situations, how should we reclaim the memory:
1) dynamically allocate memory in external functions. The Code is as follows:
Test. cpp
class Test{public: static char* m_pSZ;};char* Test::m_pSZ = NULL;void testAlloc(){ Test::m_pSZ = new char[16];}int main(){ testAlloc(); std::cout << "Already alloc for Test::m_pSZ!" << std::endl; return 0;}
By using g ++-g test. cpp-c test compilation, and then g ++-o test. the otrace is connected to the execution file, and the memory leakage detection tool valgrind is used. The command is as follows:
Valgrind -- tool = memcheck -- leak-check = full -- show-leak-kinds = all./test
The detection result is as follows:
==14924 = Memcheck, a memory error detector
= 14924 = Copyright (C) 2002-2013, and gnu gpl 'd, by Julian Seward et al.
= 14924 = Using Valgrind-3.10.1 and LibVEX; rerun with-h for copyright info
= 14924 = Command:./test
= 14924 =
Already alloc for Test: m_pSZ!
= 14924 =
==14924 === heap summary:
= 14924 = in use at exit: 16 bytes in 1 blocks
= 14924 = total heap usage: 1 allocs, 0 frees, 16 bytes allocated
= 14924 =
= 14924 = 16 bytes in 1 blocks are still reachable in loss record 1 of 1
= 14924 = at 0x402ACDB: operator new [] (unsigned int) (vg_replace_malloc.c: 383)
= 14924 = by 0x80486EE: testAlloc () (test. cpp: 13)
= 14924 = by 0x8048703: main (test. cpp: 18)
= 14924 =
= 14924 = leak summary:
= 14924 = definitely lost: 0 bytes in 0 blocks
==14924 = indirectly lost: 0 bytes in 0 blocks
==14924 = possibly lost: 0 bytes in 0 blocks
= 14924 = still reachable: 16 bytes in 1 blocks
= 14924 = suppressed: 0 bytes in 0 blocks
= 14924 =
= 14924 = For counts of detected and suppressed errors, rerun with:-v
= 14924 = error summary: 0 errors from 0 contexts (suppressed: 0 from 0)
According to the above results, there are still leaks. The leak type belongs to "still reachable". For such leaks, I checked them online:
Memory leakage can be divided into two types:
One is that the program has a pointer to the memory applied through malloc or new, but it has not been withdrawn before the program ends. If the memory is continuously increased, the memory may be exhausted. However, after the program ends, the system automatically recycles the memory.
Another is the memory applied through malloc or new, but there is no pointer in the program to the requested memory. The program has been running, causing more and more leaked memory, which may exhaust the heap memory of the program.
In the valgrind Report, the first memory leakage is represented as "still reachable ".
For memory leakage in the second case, the valgrind report indicates "Directly lost and Indirectly lost"
In addition, for the "possibly lost" in the valgrind report, the pointer does not point to the beginning of the application heap. For example, the c ++ string has the memory pool concept. If the program uses a string and exits abnormally (for example, use the ctrl + c shortcut to terminate the Program), "possibly lost" is reported ".
According to the above analysis, the memory leakage of the "still reachable" type does not affect the memory. After the program ends, it will automatically recycle them. However, you can also clear the static member pointer memory of this class and delete [] Test: m_pSZ directly in main.
2) In the static member function of the class, the static member variables are dynamically allocated with memory. Where should the memory be recycled? In static member functions? Or anywhere? In a blog post, the blogger said: "In the lifecycle of a class, static members of the class cannot be deleted ". if the static member of the delete class is a core member in the lifecycle of the class, the following code is used for testing:
Test_3.cpp
# Include <iostream> class B {private: static char * m_pSZ; public: inline B () {if (NULL = m_pSZ) {m_pSZ = new char [8];} inline ~ B () {if (m_pSZ! = NULL) {delete [] m_pSZ ;}}; char * B: m_pSZ = NULL; int main () {B B; std :: cout <"is in the class lifecycle! "<Std: endl; return 0 ;}
In the above Code, m_pSZ must be the same as the class life cycle, and the life cycle of object B must be shorter than m_pSZ, but it does not hinder the release of memory before m_pSZ life cycle, the m_pSZ pointer is a static variable in the global area of the memory, and the Pointer Points to the heap memory. If you can obtain a pointer to a memory segment in the heap, why can't you release it, not suitable. In practice, after simple compilation and running, there is no dump core phenomenon.
The results of valgrind tool detection are as follows:
Valgrind -- tool = memcheck -- leak-check = full -- show-leak-kinds = all./test_3
==15418 = Memcheck, a memory error detector
= 15418 = Copyright (C) 2002-2013, and gnu gpl 'd, by Julian Seward et al.
= 15418 = Using Valgrind-3.10.1 and LibVEX; rerun with-h for copyright info
= 15418 = Command:./test_3
= 15418 =
Is in the class lifecycle!
= 15418 =
==15418 === heap summary:
= 15418 = in use at exit: 0 bytes in 0 blocks
= 15418 = total heap usage: 1 allocs, 1 frees, 8 bytes allocated
= 15418 =
= 15418 = All heap blocks were freed -- no leaks are possible
= 15418 =
= 15418 = For counts of detected and suppressed errors, rerun with:-v
= 15418 = error summary: 0 errors from 0 contexts (suppressed: 0 from 0)
Therefore, for the static member variable pointer of the class to dynamically allocate memory, you can release the dynamically allocated memory wherever the static member variable pointer can be accessed before the program ends, or release is not displayed, because the system automatically recycles the program after it is completed.
Finally, for the test_3.cpp code, the class constructor dynamically allocates memory, which is equal to multiple objects sharing the static variable pointer. Therefore, if an object is destructed, the memory is released, if other objects still use the shared static variable pointer, It is a null pointer !, Therefore, a better design is to use static variables to maintain a reference count. Each time an object is created, the reference count is increased by 1. In the destructor, the reference count is reduced by one, the memory is not released until it is 0. The Code is as follows:
# Include <iostream> class B {private: static char * m_pSZ; static unsigned int m_count; public: inline B () {if (NULL = m_pSZ) {m_pSZ = new char [8];} + m_count; std: cout <m_count <std: endl;} inline ~ B () {if (m_pSZ! = NULL) {-- m_count; if (0 = m_count) {delete [] m_pSZ; m_pSZ = NULL ;}} std: cout <m_count <std :: endl ;}; char * B: m_pSZ = NULL; unsigned int B: m_count = 0; int main () {std :: cout <"is in the class lifecycle! "<Std: endl; B B B; B b1; B b2; B b3; return 0 ;}
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.