Re[3]: ((SA*)0)->Func();
От: VVV Россия  
Дата: 28.04.02 10:47
Оценка: 6 (1)
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте IT, Вы писали:


IT>>Здравствуйте DarkGray, Вы писали:


DG>>>Должен ли по стандарту работать следующий код?


IT>>Давай перепишем и посмотрим причём тут стандарт:


IT>>
IT>>struct SA
IT>>{
IT>>  void Func(); //невиртуальная и не важно

DG>//как раз важно что функция не виртуальная, для виртуальной функции все будет падать со свистом при нулевом указателе

IT>>  static void StaticFunc();
IT>>};

IT>>void f(SA*)
IT>>{
IT>>  SA->Func(); // откуда компилятору знать, что у программера на уме
IT>>}

IT>>void main()
IT>>{
IT>>  SA::StaticFunc(); // можно обойтись и без объекта
IT>>  f((SA*)0);        // мало ли чего можно компилятору подсунуть
IT>>}
IT>>


DG>Наверное, не правильно вопрос задал...


DG>Написано ли где-нибудь в стандарте, что компилятор не должен закладываться на то, что this всегда не равен нулю?


DG>Для виртуальный функций — понятно. Компилятор не явно закладывается на то, что this не нуль и этот указатель использует в своих целях, по нему ищет таблицу виртуальных функции.

DG>В случае нулевого указателя все падает.

DG>Для статик функции то же — понятно, так как this-а у них совсем нет.


DG>А вот для обычных функций не понятно. Могу ли я в качестве this при вызове использовать произвольное значение (в частности NULL) или не могу? То есть будет это приводить к падению или не будет?


Если посмотреть с другой стороны, то любой вызов C++ функции можно описать в терминам C функции, т.е. это будет функция, где первым параметром передаётся указатель на какую-то структуру даннык (this). Посему, при вызове такой функции из C этот параметр (this) можно задать каким угодно (и NULL в том числе). Например, если посмотреть МАПИшные примеры, то там все указатели проверяются на валидность, например так:

/* BAD_STANDARD_OBJ
 *
 * This macro insures that the object is a writable object of the correct size
 * and that this method belongs to the object.
 *
 * NOTES ON USE!
 *  This depends upon using the standard method of declaring the object
 *  interface.
 *
 *  prefix is the method prefix you chose when declaring the object interface.
 *  method is the standard method name of the calling method.
 *  lpVtbl is the name of the lpVtbl element of your object.
 */
#define BAD_STANDARD_OBJ( lpObj, prefix, method, lpVtbl)     (   IsBadWritePtr( (lpObj), sizeof(*lpObj))      || IsBadReadPtr( (void *) &(lpObj->lpVtbl->method), sizeof(LPVOID))      ||( ( LPVOID) (lpObj->lpVtbl->method) != (LPVOID) (prefix##method)))

#define FBadUnknown( lpObj )     (   IsBadReadPtr( (lpObj), sizeof(LPVOID) )      || IsBadReadPtr( (lpObj)->lpVtbl, 3 * sizeof(LPUNKNOWN) )      || IsBadCodePtr( (FARPROC)(lpObj)->lpVtbl->QueryInterface ))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.