информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Spanning Tree Protocol: недокументированное применениеГде водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Google закрывает безлимитные Photos 
 Имя компании как средство XSS-атаки 
 Утекший код XP и Windows Server... 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / beginners
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Господа, будьте снисходительны, не бросайтесь сразу штрафовать за, как вам кажется, глупые вопросы - beginners на то и beginners.
заморочка с dynamic_cast 09.12.04 15:11  
Автор: zelych Статус: Member
<"чистая" ссылка>
решил тут, как-то попользовать dynamic_cast (не слишком я люблю rtti, но тут вот приспичило)..

как написано в msdn`е, если dynamic_cast не может преобразовать указатель к нужному типу генерируется исключение bad_cast, а если объект по указателю вообще не содержит rtti информации, то генерируется исключение __non_rtti_object..
ну а мне как-раз этого-то и надо.. хотел отделять мусорные указатели от настоящих..

не получилось..
вот небольшой исходничек:

#include <stdio.h>

class A {
int x;
public:
A(){ x = 0; }
int fun() { return x; }
};

class B : public A {
public:
B() { y = 1; }
int y;
};

void* get_ptr() { return */(void-1 /*/ new B/**/; }

void main()
{
A *x, *y = (A*) get_ptr();

try {
x = dynamic_cast<A*>( y );
} catch(...){
x = 0;
}

if( x ) printf( "%i", x->fun() );
}

вроде правильно, и rtti в свойствах проекта включил, только вот компилятор почему-то генерирует такой вот код (в release конфигурации):

void main()
{
A *x, *y = (A*) get_ptr();
try {
x = dynamic_cast<A*>( y );

00401000 or eax,0FFFFFFFFh

} catch(...){ x = 0; }

if( x ) printf( "%i", x->fun() );

00401003 mov eax,dword ptr [eax]
00401005 push eax
00401006 push offset string "%i" (4060FCh)
0040100B call printf (401016h)

получается, что на весь RUN-TIME в rtti ему пофигу..

просвятите, пожалуйста, откуда трабл такой..
Вообще-то dynamic_cast от указателя возвращает нулевой указатель, а не швыряет исключение. 09.12.04 16:34  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка>
по поводу исключений - вычитано в msdn`е, да и нулевой указатель он не возвращает (хотя, судя по тому же msdn`у - должен) 09.12.04 16:43  
Автор: zelych Статус: Member
<"чистая" ссылка>
Ну что сказать - безобразие, что не возвращает... 10.12.04 14:04  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка>
В целом по использованию приведений типа см. цитату amirul'а из Страуструпа. А надежного способа определения мусорных указателей в C++, увы, нет и не предвидится.
Универсального способа определения мусорного указателя вообще не существует, имхо (update) 10.12.04 15:24  
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 10.12.04 15:34  Количество правок: 3
<"чистая" ссылка>
> В целом по использованию приведений типа см. цитату
> amirul'а из Страуструпа. А надежного способа определения
> мусорных указателей в C++, увы, нет и не предвидится.
Вернее можно внедрить в язык то, что можно сделать средствами C++ уже сейчас. Речь о том, чтобы сделать ВСЕ классы своей иерархии наследниками одного базового, например CObject

Ну и после этого делать что то типа:

class CObject {
private:
	static const unsigned long ExpectedSignature = 0x12345678; // Какое нить достаточно случайное число
	unsigned long Signature;

public:
	CObject(): Signature(ExpectedSignature) {}
	virtual ~CObject() = 0;

	bool IsObject() {
		__try {
			return (Signature == ExpectedSignature);
		} __except (EXCEPTION_EXECUTE_HANDLER) {
			return false;
		}
	}
};

---

ну и использовать как нибудь так:

void
f(void *ptr) {
	CObject *object = reinterpret_cast<CObject *>(ptr);

	if (object->IsObject()) {
		deriv = dynamic_cast<CMyDerivedClass *>(object);
	} else {
		throw bad_cast();
	}
}

---

Вероятность того, что под этим указателем будет память и при этом будет содержать нужную сигнатуру будет меньше, чем 2^(-32)

Хотя эта самая сигнатура является ничем иным как полем типа, которое в C++ не рекомендуется. Опять таки повторюсь, что не знаю ни одной ситуации, которая бы привела к ПОЛНОЙ потере информации о типе в C++. Скорее всего дизайн проекта сделан не совсем верно. Если скажут, какую задачу нужно решить с помощью динамического кастования, то возможно мы найдем другой способ

-----------------
В вышеприведенном коде вместо микрософтовского SEH вполне можно использовать стандартные try/catch блоки
Для использования RTTI класс должен быть абстрактным 09.12.04 15:42  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> class A {
> int x;
> public:
> A(){ x = 0; }
> int fun() { return x; }
> };
>
> class B : public A {
> public:
> B() { y = 1; }
> int y;
> };
То бишь иметь виртуальные функции.


> просвятите, пожалуйста, откуда трабл такой..
А вообще использование RTTI чаще всего говорит о плохой архитектуре проекта. Лучше пересмотри, мож чего можно сделать с помощью обычных виртуальных функций и статической типизации
Неправда твоя. 09.12.04 16:29  
Автор: Ktirf <Æ Rusakov> Статус: Elderman
<"чистая" ссылка>
Для использования RTTI необходимо и достаточно включить флажок у компилятора.
Ладно, мож это устаревшая информация 09.12.04 16:37  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> Для использования RTTI необходимо и достаточно включить
> флажок у компилятора.
Как доберусь до страуструпа - скажу точнее. Но я точно помню, что он писал про то, что инфа для RTTI хранится в vtbl-е, а vtbl создается если есть виртуальные функции. Мож это расширение от микрософта, а мож я чего-й-то гоню. Надо проверить
Добрался до страуструпа 10.12.04 12:50  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
Итак

1. Для кастинга, который можно сделать обычным static_cast-ом (от дочернего класса к базовому) поведение dynamic_cast-а совпадает со статическим.

2. Для downcasting-а (вниз по иерархии, то бишь от базового к наследнику) необходимо чтобы кастуемая переменная (а не тип в который она кастуется) имела полиморфный (перед этим я ошибочно назвал его абстрактным) тип. То бишь иметь виртуальные функции.
То есть, если хочется сделать
dynamic_cast<T *>(ptr);
То ptr - ОБЯЗАТЕЛЬНО должен иметь полиморфный тип, а T - может быть любым (в том числе и конкретным классом)

3. dynamic_cast к указателю в случае ошибки всегда возвращает NULL. Исключения бросает кастинг к ссылке:
dynamic_cast<T &>(var);
в случае когда такое приведение невозможно (во всех случаях когда вернулся бы указатель NULL)

Теперь замечания. Я не могу придумать ни одного случая, когда в C++ полностью теряется информация о типе (то бишь об указателе известно только то, что он void *). Вообще в C++ не так уж часто применяется (void *)
спасибо, теперь вроде ясно.. 10.12.04 18:02  
Автор: zelych Статус: Member
<"чистая" ссылка>
> 1. Для кастинга, который можно сделать обычным
> static_cast-ом (от дочернего класса к базовому) поведение
> dynamic_cast-а совпадает со статическим.

похоже, именно это и происходит..

> Теперь замечания. Я не могу придумать ни одного случая,
> когда в C++ полностью теряется информация о типе (то бишь
> об указателе известно только то, что он void *). Вообще в
> C++ не так уж часто применяется (void *)

а я, вот, придумал..
трабл такой получается при объединении моих объектов с WinAPI..
И где именно ты теряешь тип? 10.12.04 18:57  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> а я, вот, придумал..
> трабл такой получается при объединении моих объектов с
> WinAPI..
Не верю :-)
Сам неоднократно швырял указатели в WinAPI. Но при этом точно знал, что как минимум на какой-то базовый объект данный указатель указывает. Уточни задачу - мож чего и придумаем
CreateWindow -> CBT Hook 14.12.04 16:54  
Автор: zelych Статус: Member
<"чистая" ссылка>

> Сам неоднократно швырял указатели в WinAPI. Но при этом
> точно знал, что как минимум на какой-то базовый объект
> данный указатель указывает. Уточни задачу - мож чего и
> придумаем

В CreateWindow последним аргументом кладу указатель на некоторый объект, который будет ассоциироваться с окном..
При этом, хуком отлавливаю все создания окон и заношу в списочек hwnd окна и через CBT_CREATEWND вытаскиваю lpParam - последний аргумент CreateWindow..
Естественно, пару лишних движений мышкой - и винда насоздаёт кучу окошек, у которых lpParam указыавет на какую-то хрень..

вот их-то и надо отсеять..
такие дела..


и ещё до кучи.. что бы немного отвлечься..
В msdn`е написано:
"Bitmaps as Brushes
A number of functions use the brush currently selected into a device context to perform bitmap operations. For example, the PatBlt function replicates the brush in a rectangular region within a window, and the FloodFill function replicates the brush inside an area in a window bounded by the specified color (unlike PatBlt, FloodFill does fill nonrectangular shapes). "

получается что можно использовать картинку в качестве кисточки, хотело поробовать, но не получилось.. никак не ругается, но вместо картинок просто белым цветом закрашивает..
Ну тогда наверное сигнатурку надо, как выше показано 14.12.04 17:58  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка>
> получается что можно использовать картинку в качестве
> кисточки, хотело поробовать, но не получилось.. никак не
> ругается, но вместо картинок просто белым цветом
> закрашивает..
Я с GDI не слишком, но сделал ли ты SelectObject перед рисованием.
С этим делом разобрался.. 15.12.04 12:16  
Автор: zelych Статус: Member
<"чистая" ссылка>
причём совершенно мистическим способом:
сегодня утром решил ещё раз посмотреть хелп.. вместо раздела Bitmaps открываю Brushes->Brush Functions и обнаруживаю там CreatePatternBrush..
не катит [upd] 09.12.04 16:03  
Автор: zelych Статус: Member
Отредактировано 09.12.04 16:10  Количество правок: 1
<"чистая" ссылка>
> То бишь иметь виртуальные функции.

class A {
int x;
public:
A(){ x = 0; }
virtual int fun() { return x; }
};

class B : public A {
public:
B() { y = 1; }
int y;
virtual int fun() { return y; }
};

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

> А вообще использование RTTI чаще всего говорит о плохой
> архитектуре проекта. Лучше пересмотри, мож чего можно
> сделать с помощью обычных виртуальных функций и статической
> типизации

ну, наверное, не зря он есть..
а если без него, то как?? всё что приходит мне в голову, можно рассматривать как собственную реализацию rtti.. иначе придумать не умею..


[upd] PS имхо, абстрактные - классы у которых не все функции реализованы.. и в с++ их делать нельзя..
1






Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2020 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach