Почему в отчете памяти Visual Studio CRT отображаются блоки CRT
Я практикую использование библиотеки CRT, чтобы найти утечки памяти. Я написал такой код:
#define _CRTDBG_MAP_ALLOC
#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h>
typedef struct NodeLL {
int value;
struct NodeLL *next;
} Node;
void printLL(Node *pHead) {
int i=0;
while(pHead) {
printf("%d\n", pHead->value);
i++;
pHead = pHead->next;
}
}
Node * addNode(Node *pHead, int value) {
Node *pNew, *pLL;
pNew = (Node *)malloc(sizeof(Node));
pNew->value = value;
pNew->next = NULL;
if(!pHead) {
pHead = pNew;
}
else {
pLL = pHead;
while(pLL->next)
pLL = pLL->next;
pLL->next = pNew;
}
return pHead;
}
void deleteNodes(Node *pHead) {
Node *pLL;
int i=0;
while(pHead) {
printf("deleting node %d, value is %d\n", i, pHead->value);
i++;
pLL = pHead->next;
free(pHead);
pHead = pLL;
}
}
Node * removeDups(Node *pHead) {
if (!pHead)
return NULL;
Node *pNode2, *pPrev;
Node *pNode = pHead;
while(pNode) {
pPrev = pNode;
pNode2 = pNode->next;
while(pNode2) {
if(pNode2->value == pNode->value) {
pPrev->next = pNode2->next;
free(pNode2);
pNode2 = pPrev->next;
}
else {
pPrev = pNode2;
pNode2 = pNode2->next;
}
}
pNode = pNode->next;
}
return pHead;
}
int main() {
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
//_CrtSetBreakAlloc(71); // used to break at the second malloc
_CrtMemState s1, s2, s3;
// take a snap shot of memory before allocating memory
_CrtMemCheckpoint(&s1);
int NodeNum, i, j, value;
Node *pHead = NULL;
printf("How many nodes in the linked list?");
scanf("%d", &NodeNum);
for (i=0; i<NodeNum; i++) {
printf("Please enter Node %d value:", i);
scanf("%d", &value);
pHead = addNode(pHead, value);
}
printLL(pHead);
printf("remove duplicates\n");
pHead = removeDups(pHead);
printLL(pHead);
// clean up
//deleteNodes(pHead);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
_CrtDumpMemoryLeaks();
// take a snap shot of memory after allocating memory
_CrtMemCheckpoint(&s2);
if(_CrtMemDifference(&s3, &s1, &s2) )
_CrtMemDumpStatistics(&s3);
return 0;
}
Я получаю следующий вывод:
Detected memory leaks!
Dumping objects -> ...
\2_1_removedupll\removedupsll.cpp(23) : {72} normal block at 0x00701570, 8 bytes long.
Data: < > 03 00 00 00 00 00 00 00
\2_1_removedupll\removedupsll.cpp(23) : {71} normal block at 0x00701528, 8 bytes long.
Data: < p p > 02 00 00 00 70 15 70 00
\2_1_removedupll\removedupsll.cpp(23) : {70} normal block at 0x007014E0, 8 bytes long.
Data: < ( p > 01 00 00 00 28 15 70 00
Object dump complete.
0 bytes in 0 Free Blocks.
24 bytes in 3 Normal Blocks.
*4096 bytes in 1 CRT Blocks.*
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 3870 bytes.
Total allocations: 4120 bytes.
Он обнаружил протекшие 24 байта обычных блоков. Я ожидал этого. Но что это за 4096 байт в 1 ЭЛТ-блоках? По словам Microsoft:
Блок CRT выделяется библиотекой CRT для собственного использования. Библиотека CRT обрабатывает освобождение для этих блоков. Поэтому маловероятно, что вы увидите их в отчете об утечке памяти, если что-то не так, например, библиотека CRT повреждена.
Должен ли я просто игнорировать эти 4096 байтов? Благодарю.
3 ответа
Это распределение 4,096 байт является временным буфером для stdout
, который выделяется при первом звонке printf
, Потому что вы сначала позвоните printf
находится между вашими двумя контрольными точками памяти, это выглядит как разница между двумя контрольными точками. Если вы добавите звонок в printf
до вашей первой контрольной точки памяти, это распределение 4,096 байт не появится в разнице.
Этот буфер освобождается, когда CRT завершается нормально.
Кажется, действительно есть некоторые утечки. Я проверил ваш код с Deleaker и посмотрите, что у меня есть:
Также, если я ставлю точку останова на строку с free (), я никогда не попаду туда в случае ввода двух одинаковых значений.
Если я ввожу два разных значения, я нажимаю free () один раз (в функции removeDups()). Только однажды.
Очевидно, что-то не так с кодом! Вам не нужно вызывать deleteNodes() в конце концов?
Да, блоки ЭЛТ можно безопасно игнорировать. Выделение не было выполнено вашим кодом, поэтому вам не нужно беспокоиться об этом