LINUX.ORG.RU

g++ + pimpl + auto_ptr


0

1

добрый день. имеется код

a.h

class A_impl;

class A {
public:
	A();

private:
	std::auto_ptr<A_impl> m_p;
};

a.cpp

#include "header.h"

using namespace std;

class A_impl {
public:
	A_impl()
	{
		cout << "created" << endl;
	}

	~A_impl()
	{
		cout << "destroyed" << endl;
	}
};

A::A() : m_p(new A_impl)
{

}

main.cpp

#include "a.h"

int main()
{
	A a;
	return 0;
}

в нем есть ошибка (auto_ptr не может удалить объект неполного типа, если деструктор класса А не описать в месте определения типа, в данном случае в a.cpp). VS срет праведными варнингами, g++ (4.4.4, 4.5.2) почему то молчит. собирать пытался так:

g++ -Wall -Wextra --pedantic a.cpp main.cpp
ни единого разры[ESC]bcwварнинга. можно ли заставить? спасибо.

пс. воинам интернета. мне просто интересно, почему g++ молчит. auto_ptr в пимплах я не использую

★★★★★

Последнее исправление: vvviperrr (всего исправлений: 2)

>auto_ptr не может удалить объект неполного типа, если деструктор класса А не описать в месте определения типа, в данном случае в a.cpp

А, собственно, почему? Стандарт? По мне так - нормально.

JackYF ★★★★
()
Ответ на: комментарий от JackYF

когда auto_ptr вызовет деструктор объекта, которым владеет, он должен видеть его определение (а он не увидит, ибо auto_ptr инстанципуется в хидере, ~A же генерится компилем, до определения пимпла не доберется).

vvviperrr ★★★★★
() автор топика

Тоже недавно нашёл это. Причём если вместо автопоинтера ручками написать ~A() { delete m_p; }, то повоняют обе версии компилятора.

const86 ★★★★★
()

Если использовать boost::scoped_ptr, то warning'ов нет.

Я раньше использовал auto_ptr для pimpl, пока не попробовал собрать всё под MSVS, и оно даже работало как надо, несмотря на эти warning'и.

undet
()
Ответ на: комментарий от const86

че? если автопоинтер заменить на обычный поинтер и в ~A() делать delete m_p? ничего вонять не будет, валиндный код (за исключением копирующего конструктора и оператора присваивания по умолчанию, естественно)

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от const86

только естественно, деструктор нужно определить в месте определения пимпла, иначе та же проблема

но все это фигня. меня волнует то, что g++ никак на это не реагирует варнингами. может какой ключ нужно использовать или это недочет компилятора или еще что

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от vvviperrr

> только естественно, деструктор нужно определить в месте определения пимпла, иначе та же проблема

Вот и я о том же.

но все это фигня. меня волнует то, что g++ никак на это не реагирует варнингами. может какой ключ нужно использовать или это недочет компилятора или еще что

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

const86 ★★★★★
()
Ответ на: комментарий от const86

попробовал на работе на mingw версии 3.4.5, варнинги есть! причем без дополнительных ключей.

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от const86

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

vvviperrr ★★★★★
() автор топика
Ответ на: комментарий от vvviperrr

Вы не видите предупреждений потому что они находятся внутри системных заголовков, а такие предупреждения по умолчанию не показываются...

g++ -W -Wall -Wextra -pedantic -Wsystem-headers -std=gnu++0x a.cpp main.cpp -o main

/usr/include/c++/4.4/backward/auto_ptr.h: In destructor ‘std::auto_ptr<_Tp>::~auto_ptr() [with _Tp = A_impl]’:
a.h:5:   instantiated from here
/usr/include/c++/4.4/backward/auto_ptr.h:168: warning: possible problem detected in invocation of delete operator:
/usr/include/c++/4.4/backward/auto_ptr.h:168: warning: invalid use of incomplete type ‘struct A_impl’
a.h:3: warning: forward declaration of ‘struct A_impl’
/usr/include/c++/4.4/backward/auto_ptr.h:168: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.

почему C++ вообще допускает такое: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.

я хз... :)

Eshkin_kot ★★
()
Ответ на: комментарий от vvviperrr

Оказывается это по стандарту (Пункт 5.3.5 Delete стр. 83), неопределённое поведение. Зачем так в стандарте было сделано мне всё ещё не ясно :)

If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined.

Eshkin_kot ★★
()
Ответ на: комментарий от Eshkin_kot

>-Wsystem-headers

Сто очков уважения. Век живи...

JackYF ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.