Неполные утечки памяти Типа?

Используя расширенный вставляет в дампы, должен сделать импорт быстрее.

5
задан James McNellis 20 November 2009 в 01:32
поделиться

5 ответов

Это часто случается при использовании Pimpl, поэтому я сосредоточусь на решении там:

class FooImpl;

class Foo
{
public:
  // stuff
private:
  Pimpl<FooImpl> m_impl;
};

Проблема здесь в том, что если вы не объявите деструктор, он будет автоматически сгенерирован встроенным компилятором. Но, конечно, компилятор не будет иметь представления о полном типе FooImpl там.

Таким образом, вы должны явно определить деструктор, даже если он пуст, и поместить определение где-нибудь, где полный тип FooImpl виден.

// cpp file
class FooImpl
{
};

Foo::~Foo() {} // Empty, but now correctly generated
               // because FooImpl complete at this point.

Кроме того,

6
ответ дан 18 December 2019 в 13:15
поделиться

Согласно стандарту C ++ (ISO / IEC 14882: 2003 5.3.5 / 5):

Если удаляемый объект имеет неполный тип класса на момент удаления, а полный класс имеет нетривиальный деструктор или функция освобождения, поведение не определено.

Итак, если в вашем классе есть нетривиальный деструктор, не делайте этого, независимо от того, как Visual C ++ обрабатывает эту ситуацию.

6
ответ дан 18 December 2019 в 13:15
поделиться

In g++, the warning could be reproduced too using following code:

class A;

void func(A *p)
{
        delete p;
}

int main(int argc, char **argv)
{
        return 0;
}

Warnings but no any errors:

test.cpp: In function void func(A*):
test.cpp:6: warning: possible problem detected in invocation 
  of delete operator:
test.cpp:4: warning: A has incomplete type
test.cpp:2: warning: forward declaration of struct A
test.cpp:6: note: neither the destructor nor the class-specific
  operator delete will be called, even if they are declared
  when the class is defined.

While g++ states very clear here that destructor will not be called because it doesn't know whether needs a destructor or not, or where is the destructor.

In this case delete() downgrates to the C call free(), that is, it just free the object memory itself, but any heap data allocated by the object itself internally (e.g., in constructor) will be keeped, the same behavior as free(p).

I think it would be a similar way if in MS VC/++; and a correct way is you to include the interface headers of A.

1
ответ дан 18 December 2019 в 13:15
поделиться

It sounds like you're not following the p-impl idiom correctly.

Brief example:

// header
struct Other; // declare to use a pointer to it

struct Handle {
  Handle();
  ~Handle();

  void f();

private:
  Other* _obj;
};

// implementation (.cpp)
#include "header"

struct Other {
  void f();
};

Handle() : _obj(new Other()) {}
~Handle() { delete _obj; }

void Handle::f() { _obj->f(); }

Since using delete is now after the definition of class Other, the type will be complete. Without a complete type, the compiler can't know how to properly destroy it. (E.g. the dtor could be virtual or non-virtual, or even might be non-public.)

0
ответ дан 18 December 2019 в 13:15
поделиться

У вас может не быть утечек, даже если деструктор не вызван, если удаляемый объект не содержит указателей на объекты, размещенные в куче. Однако не пытайтесь это сделать - как упоминает Джеймс Макнеллис в в своем ответе , это неопределенное поведение в соответствии со стандартом C ++.

Когда вызывается delete (явно или из умного указателя) сначала запускается деструктор объекта, а затем освобождается память. VC ++ в основном сообщает вам, что он не знает, какой деструктор запускать, и поэтому не будет запускать его, а просто освободит память. Если объект относится к типу POD или у него нет указателей, установленных на объекты, размещенные в куче (либо они не содержат указателей, либо содержат указатели с нулевым значением или на объекты, принадлежащие кому-то другому и, следовательно, не требующие освобождения), нет причин для утечки.

Так что, возможно, VC ++ будет производить то же поведение, что и при первом приведении объекта к void * . Но опять же, не полагайтесь на это - в лучшем случае у вас будет непереносимый код, в худшем - ваш код развалится, как только вы измените версию или исправите свой компилятор VC ++.

1
ответ дан 18 December 2019 в 13:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: