C ++ макрос, вызывающий нулевой указатель - PullRequest
1 голос
/ 11 августа 2011

Мне было интересно, может ли кто-нибудь объяснить мне этот макрос.

#define Q_DECLARE_PRIVATE(Class) \

inline Class##Private* d_func() { return reinterpret_cast<Class##Private
*>(d_ptr); } \

inline const Class##Private* d_func() const { return reinterpret_cast<const
Class##Private *>(d_ptr); } \

friend class Class##Private;

У меня есть приложение, использующее QT, которое аварийно завершает работу с исключением нарушения прав доступа в последней строке следующего фрагмента.

class Q_GUI_EXPORT QWidget : public QObject, public QPaintDevice
{
    Q_OBJECT
    Q_DECLARE_PRIVATE(QWidget)

( полный источник здесь )

и что может вызвать операцию с нулевым указателем в последней строке?

Ответы [ 4 ]

3 голосов
/ 11 августа 2011

Компилятор может объяснить это лучше всего:

g++ -E foo.cc

поместит foo.cc в стандартный вывод после прохождения через препроцессор. Это позволяет вам увидеть то, что видит компилятор, что (особенно при вставке токенов) обычно менее чем очевидно.

1 голос
/ 11 августа 2011

Из заголовка Windows:

#define DECLARE_HANDLE(name) struct name##__ {int unused;} typedef name##__* name;

И использование:

DECLARE_HANDLE(YourHandeType); // Just any name, this isn't any type

создаст новую структуру как:

struct YourHandleType__
{ 
   int unused;
};
typedef YourHandleType__ * YourHandleType;

Где YourHandleType будет указателем типа YourHandleType__

Оператор токенизатора ## будет использоваться препроцессором для создания полного имени, которое будет использоваться компилятором C / C ++. В этом случае DECLARE_HANDLE может создавать различные типы, которые будут непрозрачны для вызывающей стороны, и при этом обеспечивать «отсутствие преобразования» между различными дескрипторами.

1 голос
/ 11 августа 2011

Макросы реализуют идиому Pimpl, объявляя указатель на частный класс реализации. Мусор ## создает имя для частного класса с помощью оператора сцепления препроцессора.

Если извлечение элемента d_ptr вызывает доступ NULL, то вызывающая сторона должна выполнить NULL->d_func(). Ищите это и отлаживайте звонящего.

1 голос
/ 11 августа 2011

Ваш this указатель NULL?Все, что делает этот код, это генерирует функции доступа для члена класса d_ptr.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...