# V780. The object of non-passive (non-PDS) type cannot be used with the function.

Анализатор обнаружил опасную работу со сложными типами. Если объект не является Passive Data Structure (PDS), то нельзя использовать низкоуровневые функции по работе с памятью: memset, memcpy и т.д. Это может нарушить логику работы класса и привести к утечке памяти, двойному очищению одного ресурса или Undefined Behavior.

Пример классов, над которыми нельзя совершать такие действия: std::vector, std::string и другие подобные контейнеры.

Иногда такая диагностика находит опечатки. Рассмотрим пример:

    struct Buffer {
      std::vector<char>* m_data;

      void load(char *buf, size_t len) {
        m_data->resize(len);
        memcpy(&m_data[0], buf, len);
      }
    };

Функция 'memcpy' копирует данные не в содержимое контейнера, а в объект, на который указывает 'm_data'. Такой код нужно переписать следующим образом:

    memcpy(&(*m_data)[0], buf, len);

или:

    memcpy(m_data->data(), buf, len);

Другой способ ошибиться - это использовать memset/memcpy для структуры, полями которой являются non-PDS объекты. Рассмотрим пример:

    struct Buffer {
      std::vector<char> m_data;
      ....
    };

    void F() {
      Buffer a;
      memset(&a, 0, sizeof(Buffer));
      ....
    }

Чтобы избежать таких ошибок можно рекомендовать использовать value initialization. Такой подход корректно работает и с POD-данными, и с объектами с нетривиальным конструктором.

Для копирования можно положиться на генерируемый компилятором конструктор копирования или написать свой.

Анализатор также ищет структуры, использование memset/memcpy над которыми может быть опасно, исходя из их логики или представления в памяти. К первому случаю относятся классы, в которых одновременно есть указатели, конструкторы и деструкторы. Если в классе содержится нетривиальная работа с указателями (например, управление памятью или ресурсом), то нельзя использовать для него memcpy/memset. Пример такого класса:

    struct Buffer {
      char *buf;

      Buffer() : buf(new char[16]) {}
      ~Buffer() { delete[] buf; }
    };

    Buffer buf1, buf2;
    memcpy(&buf1, &buf2, sizeof(Buffer));

Ко второму случаю относятся классы, не являющиеся standard layout:

    struct BufferImpl {
      virtual bool read(char *, size_t) { return false; }
    };

    struct Buffer {
      BufferImpl impl;
    };

    Buffer buf1, buf2;
    memcpy(&buf1, &buf2, sizeof(Buffer));

Данная диагностика классифицируется как:

CERT-EXP62-CPP CERT-OOP57-CPP

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V780.