﻿# V773\. Function exited without releasing the pointer/handle\. A memory/resource leak is possible\.

Анализатор обнаружил потенциально возможную утечку памяти в коде\. Такая ситуация возникает, когда память, выделенная с помощью 'malloc' или 'new', не была далее освобождена\.

Рассмотрим пример такого кода:

```cpp
int *NewInt()
{
  int *p = new (std::nothrow) int;
  ....
  return p;
}

bool Test()
{
  int *p = NewInt();
  int res = *p;
  return res;
}
```

В данном примере, выделение памяти спрятано в вызове другой функции\. Соответственно после вызова нужно соответствующим образом освободить память\.

Исправленный код, где не возникает утечка памяти:

```cpp
int *NewInt()
{
  int *p = new int;
  ....
  return p;
}

bool Test()
{
  int *p = NewInt();
  int res = *p;
  delete p;
  return res;
}
```

Часто подобные ошибки можно встретить в обработчиках ошибочных ситуаций, так как к ним невнимательно относятся при обзорах кода и слабо тестируют\. Пример: 

```cpp
bool Test()
{
  int *p = (int*)malloc(sizeof(int));
  int *q = (int*)malloc(sizeof(int));
  if (p == nullptr || q == nullptr)
  {
    std::cerr << "No memory";
    return -1;
  }
  int res = *p + *q;
  free(p);
  free(q);
  return res;
}
```

Может сложиться ситуация, когда указатель 'p' будет хранить указатель на выделенную память, а 'q' будет равен 'nullptr'\. Тогда выделенная память освобождена не будет\. Кстати, может быть и наоборот\. В параллельной программе реальна ситуация, когда первый раз не удастся выделить память, а потом удастся\.

Помимо утечек памяти, анализатор может находить утечки ресурсов: незакрытые дескрипторы, файлы и т\.д\. Такие ошибки не сильно отличаются друг от друга, поэтому к ним относится всё вышесказанное\. Приведём небольшой пример:

```cpp
void LoadBuffer(char *buf, size_t len)
{
  FILE* f = fopen("my_file.bin", "rb");
  fread(buf, sizeof(char), len, f);
}
```

Примечание\. В современном C\+\+ лучше обходиться без ручного управления ресурсами и использовать умные указатели\. Например, можно рекомендовать использовать 'std::unique\_ptr'\. В этом случае вся память будет освобождена корректно во всех точках выхода функции\. Также такое решение будет exception\-safe\.

У статического анализатора меньше информации об указателях, чем у динамического, поэтому анализатор может выдавать ложные предупреждения, если память освобождается нетривиально или далеко от места, где выделяется\. Для отключения таких предупреждений предусмотрен специальный комментарий:

```cpp
//+V773:SUPPRESS, class:className, namespace:nsName
```

Параметр 'namespace' является необязательным\.

Рассмотрим пример:

```cpp
void foo()
{
  EVENT* event = new EVENT;
  event->send();
}
```

Объект класса 'EVENT' не должен удаляться в этой функции, поэтому отключить все предупреждения V773 на этот класс можно с помощью комментария:

```cpp
//+V773:SUPPRESS, class:EVENT
```