Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> smart pointer-ы, работает даже тогда когда не должно..... 
:(
    Опции темы
Master01
Дата 21.9.2008, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



всем, привет

вот решил заняться smart pointer-ами. Нашёл замечательную книжку (хочется так думать)
Джеффа Элджера и углубился в эту увлекательную областьsmile

написал вот что

Код

class CInteger 
{
private:
    int value;

public:
    __stdcall CInteger():value(0) {}
    __stdcall CInteger(int value):value(value) {}
    virtual __stdcall ~CInteger() {};

    operator int() {return value;}
    void __stdcall msgbox() { MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }
};

и
Код

class CPInteger
{
private:
    CInteger *pCInteger;
public:
    __stdcall CPInteger() { pCInteger = NULL;};
    __stdcall CPInteger(CInteger *pCInteger):pCInteger(pCInteger) {};
    virtual __stdcall ~CPInteger() {};

    operator CInteger*()   { return pCInteger; }
    CInteger* operator->() { return pCInteger; }
};


CInteger - просто некоторый класс.
CPInteger - умный указатель для него.

в Main пишу следуещее:
    CPInteger psp;
    psp->msgbox();

в результате чего на экране появляется соответствующий messadgebox, т.е. всё работает нормально.

Далее изменяю CPInteger(см. 11 строку)
Код

class CPInteger
{
private:
    CInteger *pCInteger;
public:
    __stdcall CPInteger() { pCInteger = NULL;};
    __stdcall CPInteger(CInteger *pCInteger):pCInteger(pCInteger) {};
    virtual __stdcall ~CPInteger() {};

    operator CInteger*()   { return pCInteger; }
    CInteger* operator->() { return NULL; }
};

т.е. теперь перегруженный оператор -> всегда возвращает NULL, запускаю на выполнение... ВСЁ РАБОТАЕТ!!!!!
ради смеха пробовал return reinterpret_cast<CInteger>(87878787)  и что вы думаете? во время отладки стрелочка дебаггера 
благополучно перескакивает на строчку "void __stdcall msgbox() { MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }"
, в в окошке watches значение указателя this отображается как 53CEC83!!! т.е. там есть объект...

я конечно понимаю что это smart поинтеры.. но всё жsmile

Сильно подозреваю компилятор.
использую Visual studio 2003, я в принципе на неё только пересел, может что-то не так настроил.....

Заранее спасибо.
PM MAIL   Вверх
mes
Дата 21.9.2008, 00:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Master01 @  21.9.2008,  00:04 Найти цитируемый пост)
   void __stdcall msgbox() { MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }

замени на такое :
Код

  void __stdcall msgbox() { value=0; MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }

и потестируй теперь )


--------------------
PM MAIL WWW   Вверх
Master01
Дата 21.9.2008, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



О! наконец-то, вылетело!! smile
появилось сообщение следующего содержания - "Access Violation Writing location 0x00000004".

но у меня есть 2 вопроса:
1. неужели вызов функции по адресу 0x00000000 возможен??? вроде бы само по себе действие подобного рода должно вызывать остановку программы.
2. допустим что мы всё же прыгнули на 0 адресс, но не может же быть такого чтоб там где-то в памяти случайно оказалось то что нам нужно - message box всё же появлялся и причём с правильным текстом (специально менял, чтоб убедиться). Значит всё же что-то в памяти весело.. хотя никакой объект не создавался. Откуда там это взялось?

PM MAIL   Вверх
mes
Дата 21.9.2008, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Master01 @  21.9.2008,  19:20 Найти цитируемый пост)
о у меня есть 2 вопроса:
1. неужели вызов функции по адресу 0x00000000 возможен??? вроде бы само по себе действие подобного рода должно вызывать остановку программы.
2. допустим что мы всё же прыгнули на 0 адресс, но не может же быть такого чтоб там где-то в памяти случайно оказалось то что нам нужно - message box всё же появлялся и причём с правильным текстом (специально менял, чтоб убедиться). Значит всё же что-то в памяти весело.. хотя никакой объект не создавался. Откуда там это взялось?


Эти вопросы возникли из за неправильного представления работы метода.
Метод эта такая же функция , которой неявно передается дополнительный параметр this
т.е. 

Код

    void  CInteger ::msgbox() { MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }
есть ничто иное, как
    void msgbox(CInteger *this) { MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }

вызов с нулевым обэектом такой функции никакого вреда не принесет, так как параметр this не используется
однако доработанный метод
Код

 void  CInteger::msgbox() { value=0; MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }
представляет собой такой код:
  void msgbox(CInteger *this) { this->value=0; MessageBox(NULL,"CInteger.msgbox","CInteger.msgbox",MB_OK); }


как видите при таком варианте, значение this используется.
 Поэтому теперь при вызове метода с невалидным указателем , запись значения по чужому адресу  спровоцирует Access Violation

Добавлено @ 21:45
Цитата(Master01 @  21.9.2008,  19:20 Найти цитируемый пост)
допустим что мы всё же прыгнули на 0 адресс, но не может же быть такого чтоб там где-то в памяти случайно оказалось то что нам нужно - message box всё же появлялся и причём с правильным текстом (специально менял, чтоб убедиться). Значит всё же что-то в памяти весело.. хотя никакой объект не создавался. Откуда там это взялось?


да забыл сказать, что metod и eго содержимое хранится не в объекте, а статически. А описание методов внутри класса нужно не для того , чтоб создались методы, а для чтоб ограничить права доступа к методам и для удобного наследования этих правил.  

Это сообщение отредактировал(а) mes - 21.9.2008, 21:46


--------------------
PM MAIL WWW   Вверх
J0ker
Дата 22.9.2008, 05:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



сорри за оффтопик, но зачем вам __stdcall?

Добавлено через 4 минуты и 6 секунд
Цитата(mes @  21.9.2008,  21:35 Найти цитируемый пост)
вызов с нулевым обэектом такой функции никакого вреда не принесет

если только эта функция не virtual...



--------------------
user posted image
PM MAIL   Вверх
Master01
Дата 22.9.2008, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



mes, спасибо за толковое объяснение, теперь всё ясно.

JOker, в данном примере использование __stdcall скорее привычка нежели необходимость.

всем спасибо.
вопрос закрыт. smile 
PM MAIL   Вверх
bsa
Дата 22.9.2008, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(Master01 @ 22.9.2008,  10:07)
JOker, в данном примере использование __stdcall скорее привычка нежели необходимость.

А зачем нужна эта привычка, если не секрет?  smile 
PM   Вверх
Master01
Дата 22.9.2008, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



Цитата

А зачем нужна эта привычка, если не секрет?

мне просто с COM приходилось иметь дело, а там все вызовы обязательно __stdcall, чтобы избежать проблем при написание клиента и компонента с использованием разных языков и компиляторов smile 

а вы находите что-то негативное в этом формате вызова?или просто за чистоту кода? smile 
PM MAIL   Вверх
Lazin
Дата 22.9.2008, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(Master01 @  22.9.2008,  12:05 Найти цитируемый пост)
мне просто с COM приходилось иметь дело, а там все вызовы обязательно __stdcall

не все, а только те, которые являются частью интерфейса, да и там их не нужно вручную прописывать как __stdcall, для этого используются макросы
PM MAIL Skype GTalk   Вверх
Master01
Дата 22.9.2008, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



Цитата(Lazin @ 22.9.2008,  12:13)
Цитата(Master01 @  22.9.2008,  12:05 Найти цитируемый пост)
мне просто с COM приходилось иметь дело, а там все вызовы обязательно __stdcall

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

ну ясное дело что только те, которые являются частью интерфейса - это не суть важно, я к тому что оттуда эта привычка и пошла. 

Насчёт макросов - вообще утверждение спорно. как это не нужно? почему? мне кажется кому какой стиль написания нравится, тот так и пишет... при условии, что это находится в рамках разумного конечно. smile 
PM MAIL   Вверх
Lazin
Дата 22.9.2008, 13:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(Master01 @  22.9.2008,  12:57 Найти цитируемый пост)
Насчёт макросов - вообще утверждение спорно. как это не нужно? почему? мне кажется кому какой стиль написания нравится, тот так и пишет... при условии, что это находится в рамках разумного конечно.

я имел ввиду STDMETHOD, а это уже не вопрос вкуса или стиля
PM MAIL Skype GTalk   Вверх
Master01
Дата 22.9.2008, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



Цитата(Lazin @ 22.9.2008,  13:20)
я имел ввиду STDMETHOD, а это уже не вопрос вкуса или стиля

а почему? 
PM MAIL   Вверх
Lazin
Дата 22.9.2008, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



потому что методы, которые являются частью com интерфейса, рекомендуется объявлять через макросы, для единообразия со сгенерированным по idl кодом
PM MAIL Skype GTalk   Вверх
Master01
Дата 22.9.2008, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



Цитата(Lazin @ 22.9.2008,  15:14)
потому что методы, которые являются частью com интерфейса, рекомендуется объявлять через макросы, для единообразия со сгенерированным по idl кодом

а что вручную написать virtual HRESULT __stdcall - очень большая ошибка?
PM MAIL   Вверх
mes
Дата 22.9.2008, 15:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Master01 @  22.9.2008,  15:22 Найти цитируемый пост)
а что вручную написать virtual HRESULT __stdcall - очень большая ошибка? 

дело в том , что __sdtcall предназначен для функций, а не для методов, и возможна такая реализация компилятора, где
определенный посредством директивы __stdcall метод, будет не соответствовать реальному соглашению о вызове.
Тогда как макрос STDMETHOD гарантирует соответствие.

Добавлено @ 15:29
Цитата(Master01 @  22.9.2008,  15:22 Найти цитируемый пост)
а что вручную написать virtual HRESULT __stdcall - очень большая ошибка? 

такая же как вместо этого написать virtual long __stdcall

Это сообщение отредактировал(а) mes - 22.9.2008, 15:30


--------------------
PM MAIL WWW   Вверх
Master01
Дата 22.9.2008, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



Цитата(mes @ 22.9.2008,  15:27)
Цитата(Master01 @  22.9.2008,  15:22 Найти цитируемый пост)
а что вручную написать virtual HRESULT __stdcall - очень большая ошибка? 

дело в том , что __sdtcall предназначен для функций, а не для методов, и возможна такая реализация компилятора, где
определенный посредством директивы __stdcall метод, будет не соответствовать реальному соглашению о вызове.
Тогда как макрос STDMETHOD гарантирует соответствие.

Добавлено @ 15:29
Цитата(Master01 @  22.9.2008,  15:22 Найти цитируемый пост)
а что вручную написать virtual HRESULT __stdcall - очень большая ошибка? 

такая же как вместо этого написать virtual long __stdcall

вот только что-то мне слабо вериться в существование такого компилятора, а ещё меньше в то, что он станет достаточно популярным на рынке ....

По поводу сравнения с HRESULT - тут наверно имелась ввиду информативность кода. Согласен, что при взгляде на макрос сразу ясно с какой функцией мы емеем дело... но опять же насколько это нужно?

Лично моё мнение, что использование данного макроса должно носить скорее рекомендательный характер, нежели обязательный.

ну давольно, по-моему мы увлеклись smile

PM MAIL   Вверх
Lazin
Дата 22.9.2008, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(Master01 @  22.9.2008,  16:04 Найти цитируемый пост)
Лично моё мнение, что использование данного макроса должно носить скорее рекомендательный характер, нежели обязательный.

ну здесь уже каждый сам себе злобный буратина, жизнь научит smile 


PM MAIL Skype GTalk   Вверх
mes
Дата 22.9.2008, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Master01 @  22.9.2008,  16:04 Найти цитируемый пост)
вот только что-то мне слабо вериться в существование такого компилятора, а ещё меньше в то, что он станет достаточно популярным на рынке ....

Дело не только в компиляторе,а в программисте.
написать STDMETHOD во первых гораздо легче и безопаснее , чем virtual __stdcall HRESULT - одно слово вместо трех,
а во вторых переносимее, потому что нужно всего будет определить один дефайн под конкретный компилятор.

Добавлено @ 16:17
Цитата(Master01 @  22.9.2008,  16:04 Найти цитируемый пост)

Лично моё мнение, что использование данного макроса должно носить скорее рекомендательный характер, нежели обязательный.

ага рекомендательный. Но рекомендация возникла не на пустом месте )

Цитата(Lazin @  22.9.2008,  16:11 Найти цитируемый пост)
ну здесь уже каждый сам себе злобный буратина, жизнь научит smile 

 smile

Цитата(Master01 @  22.9.2008,  16:04 Найти цитируемый пост)
что-то мне слабо вериться в

а вот реализация макроса взятая с msdn :
Код


#ifdef _WIN32   // Win32 doesn't support __export
   #define STDMETHODCALLTYPE     __stdcall
#else
   #define STDMETHODCALLTYPE     __export __stdcall
#endif

#define STDMETHOD(method)     virtual HRESULT STDMETHODCALLTYPE method

тут видно различие под разные платформы, а этого уже достаточно в качестве аргументации использования макроса. 



Это сообщение отредактировал(а) mes - 22.9.2008, 16:24


--------------------
PM MAIL WWW   Вверх
Master01
Дата 22.9.2008, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



Цитата(mes @ 22.9.2008,  16:16)
тут видно различие под разные платформы, а этого уже достаточно в качестве аргументации использования макроса.

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

PM MAIL   Вверх
J0ker
Дата 22.9.2008, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



__stdcall не является частью стандарта, поэтому использование такого кода будет существенно ограничено
и во-вторых дефолт - __cdecl - вы усложняете работу пользователям ваших классов


--------------------
user posted image
PM MAIL   Вверх
Master01
Дата 22.9.2008, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 89
Регистрация: 22.8.2007

Репутация: 2
Всего: 2



Цитата(J0ker @ 22.9.2008,  17:55)
__stdcall не является частью стандарта, поэтому использование такого кода будет существенно ограничено
и во-вторых дефолт - __cdecl - вы усложняете работу пользователям ваших классов

я ещё раз повторяю что это только лишь пример. О каком ограничении может идти речь? - она не будет работать на той системе, на которой я её написал? и каким пользователям? себе самому что ли

PM MAIL   Вверх
J0ker
Дата 22.9.2008, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 986
Регистрация: 17.9.2008

Репутация: 4
Всего: 14



Цитата(Master01 @  22.9.2008,  18:25 Найти цитируемый пост)
я ещё раз повторяю что это только лишь пример. О каком ограничении может идти речь? - она не будет работать на той системе, на которой я её написал? и каким пользователям? себе самому что ли

да ладно, не нервничайте  smile 
мы все поняли


--------------------
user posted image
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0674 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.