Здравствуйте 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 ))