2008-11-22 3 views
0

Мне нужно преобразовать указатели в long (SendMessage()) , и я хочу с уверенностью проверить, соответствует ли переменная с другой стороны. Поэтому я думал о том, чтобы делать dynamic_cast, но это не работает на классах, которые не являются виртуальными. Затем я подумал о том, что вы делаете typeid, но это будет работать, пока я не передам производный var в качестве базы.проверить, является ли X производным от Y через typeid

Есть ли способ проверить, является ли указатель тем, что я ожидаю во время выполнения? Есть ли способ, которым я могу использовать typeid, чтобы увидеть, является ли указатель типом, производным от конкретной базы?

+1

Как ваш текст вопросов связан с вашим вопросом заголовка каким-либо образом? – 2008-11-22 20:25:17

ответ

1

Если все, что у вас есть, это long, тогда вы действительно не можете многое сделать. Нет общего способа определить, является ли произвольное число действительным адресом памяти. И даже если вы знаете, что это правильный адрес памяти, нет способа определить тип объекта, на который указывает указатель. Если вы не можете быть уверены в действительном типе вещи до того, как ее адрес был отброшен до long, то вы не можете быть уверены, что это будет безопасно отличать long от любого типа, на котором вы планируете его забрасывать.

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

0

PTLib (http://sourceforge.net/projects/opalvoip/) использует макрос PCLASSINFO для определения отношений между классами. Это обеспечивает функции, такие как IsDescendant и GetClass.

Возможно, вы могли бы реализовать нечто подобное.

0

dynamic_cast работает, проверяя подпись таблицы виртуальных методов. Если у вас нет виртуальных методов, у вас нет VMT, так как вы говорите, что dynamic_cast не будет работать. Однако, если у вас нет VMT, у вас абсолютно нет знаний об объекте, на который указывают.

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

0

Я еще не понимаю, о чем идет речь.

  • Если это, можете ли вы быть уверены, что кастинг на длинный и обратно будет давать такое же значение, вид Safely checking the type of a variable
    Учитывая «Правила использования указателей» MS-Site другого Ответчика связаны, правильный тип для отливки - UINT_PTR. Таким образом, вы делаете UINT_PTR v = reinterpret_cast<UINT_PTR>(ptr);, чтобы применить к целому типу, и сделайте обратное, чтобы снова вернуть его в указатель. Стандарт C++ гарантирует, что исходное значение будет восстановлено. (см. ссылку, приведенную выше, для моего объяснения этого). Этот сайт Microsoft, кстати, также говорит о том, что WPARAM и LPARAM меняют свой размер в зависимости от платформы. Таким образом, вы можете просто использовать эту переменную v и SendMessage.
  • Если вы можете проверить на другой стороне, указывает ли указатель (преобразованный в некоторый тип указателя) на какой-либо объект, ответ вы не можете. Поскольку вы, по-видимому, не знаете, какой тип указателя использовался для его отправки, вы не можете проверить на принимающей стороне, на что указывает динамический тип, на который указывает указатель. Если вы знаете тип указателя на стороне отправителя, ваш чек не будет требоваться в первую очередь.
1

Вы не можете использовать typeid. Это приведет к Нарушению доступа, если вы получите мусор вместо действительного указателя, поэтому ваш чек не имеет смысла.

Что вы должны сделать, это обернуть ваш SendMessage и код, который обрабатывает сообщение в единый безопасный по типу интерфейс. Таким образом, вы не сможете передать неожиданные вещи SendMessage и не будете нуждаться в каких-либо проверках на стороне получателя.

Система типа C++ работает во время компиляции. Когда вы нажмете указатель на длинный, вы потеряете всю информацию о типе. Длинное количество бит в памяти; вы не можете определить, что он указывает на объект.

3

Ваша ссылка на SendMessage() заставляет меня звучать как MS Windows - это ваша платформа, а затем рекомендуется читать Rules for Using Pointers (Windows). В нем подробно описаны функции PtrToLong и PtrToUlong и другие вещи, которые Microsoft предоставляет вам в таких ситуациях.

0

В Windows MFC предоставляет метод проверки того, указывает ли данный указатель на допустимую ячейку памяти (это выполняется путем захвата segfault). Я не помню имя функции, но оно есть. Тем не менее, он не гарантирует, что содержимое указанной памяти будет действительным. Он может по-прежнему иметь недействительный VMT и сбой вашего кода. Конечно, вы можете захватить segfault самостоятельно (see MS Knowledge Base)

Что касается проверки того, что что-то принадлежит типу, вы должны иметь базовый класс для начала. Если вы создадите деструктор базового класса «virtual», все производные классы будут иметь VMT.

Если вам необходимо избегать VMT любой ценой, у вас должен быть какой-то дискриминатор, который сообщает вам, с чем вы имеете дело, например тип события в событиях MS Windows.

Смежные вопросы