Для изучения читаю и пробую упражнения из книги Д. Рассохина "От Си к Си++". В одном упражнении есть такая конструкция: cout<где char *s; //указатель на строку. И все работает, пока s не инициализируется значением NULL. Когда такое происходит, то “WindowNT 4.0 Workstation Rus” выдает сообщение: "... обратилась по адресу 0х00000000. Память не может быть "read". Как можно решить этот вопрос. Единственное, что у меня получилось, это заменить эту конструкцию на: printf("%s
",s) но хотелось бы узнать почему не работает у меня конструкция, данная в книге (хотя до этого все упражнения, на удивление, работали). И как сделать чтобы работала конструкция cout<С уважением, Александр.
Доброе время суток, Alexander! NULL - это пустой указатель, он не указывает ни на какие данные, если передавать его там где требуются адреса реальных данных то ошибки могут возникнуть не только в cout. Все зависит от того, проверяет процедура свои параметры на корректность или нет. Если хочешь чтобы у тебя "не вылетал" этот пример можешь попробовать использовать обработку исключений: try { cout < c; } catch(...) { cout < "Output error occured"; } В конце концов можно перегрузить операторы <, <<, >, >>
Ответ отправлен: 13.05.2003, 12:01 Отправитель: Knignick Отвечает baldr
Приветствую Вас, Alexander! Так зачем же ты обнуляешь указатель? Конечно, по 0x0000 ничего нельзя читать! Для чтения через указатель его необходимо инициализировать. Ответ отправлен: 13.05.2003, 12:53 Отправитель: baldr Отвечает Avl2k
Здравствуйте, Alexander! А как оно должно работать? По стандарту C++ указатель, передаваемый в operator << не должен быть нулевым (не путайте с "пустой" строкой "\0") - так что все не работает так, как надо :). С уважением, Avl2k. Ответ отправлен: 13.05.2003, 12:38 Отправитель: Avl2k Отвечает DiGiT[old]
Добрый день, Alexander! Видишь s В данном случае является переменной хранящей адрес начала первого элемента строки, константа NULL во многих компиляторах определена как 0 приведенный к типу указателя. Таким образом записав в s значение NULL ты пытаешься обратиться к области памяти, которая не принадлежит твоей программе, что вызывает ошибку обращения. Вообще разыменование указателя NULL не является разрешенным. а конструкция типа cout<<С будет работать если в качестве параметра ты будешь передавать реальный указатель. Ответ отправлен: 14.05.2003, 06:40 Отправитель: DiGiT[old] Отвечает Chorkov
Приветствую Вас, Alexander! Прежде всего, передача потоку вывода нулевого указателя, является нештатной ситуацией, и ее не следует допускать. Проблема использования не инициализированного указателя может быть решена несколькими способами: 1) Проверять указатель перед использованием: cout<<( s==NULL ? L“ <> ” : s); достоинство: Простота перехода от С-кода к С++ коду недостаток: если тип переменной s будет изменен, то придется переписат большей обем кода. 2) Проверка перед использованием может быть замаскирована, чтобы избавиться от зависимости от типа переменной S: template inline const X FilterNullPtr(const X& x) {return x;}; inline const char* FilterNullPtr(const char* x) {return x==NULL ? " <> " : x;}; inline char* FilterNullPtr(char* x) {return x==NULL ? " <>
" : x;}; …. cout<< FilterNullPtr(s); 3) Отказаться от использования char* в пользу стандартных строк #include #include using namespace std; … string s; cout<(Они инициализируются пустой строкой, и потому, всегда валидны). 4) Обрабатывать исключение, возникающие при обращении по нулевому указателю. int main(int,char**) { char*s=NULL; try{ cout< } catch(...) { return 1; }; return 0; }; Последний способ может быть рекомендован, только если появление неправильного или нулевого указателя является нештатной ситуацией, и ничего разумного, кроме сохранения данных и завершения приложения, сделать уже нельзя. P.S. К сожалению, выбранная вами книга (1993г), вышла еще до принятия современной редакции стандарта языка C++, поэтому многие очень важные возможности
языка (такие как, обработка исключений, частичная параметризация шаблонов, анонимные пространства имен, STL) в данной книге не рассмотрены. Пока не поздно, советую сменить учебник, после, привыкнув к char*, переучиваться будет труднее.
Ответ отправлен: 13.05.2003, 14:26 Отправитель: Chorkov Отвечает Shurik
Добрый день, Alexander! Читайте не указатель на строку, а саму строку, т.е. без *
Ответ отправлен: 16.05.2003, 16:17 Отправитель: Shurik Отвечает xiron
Добрый день, Alexander! Во первых правильно писать так #include char *buf = "Сдесь могла бы быть ваша рекламма"; cout << buf; "... обратилась по адресу 0х00000000. Память не может быть "read" - ну скорее всего после инициализации NULL -ом его никто и не меняет. Хоть бы исходниками кинулся, для более конкретного ответа. Наверное в книге опечатка. Ответ отправлен: 14.05.2003, 16:25 Отправитель: xiron Отвечает BOLT
Приветствую Вас, Alexander! "cout<где char *s; //указатель на строку." - это вообще как понимать, друг?Я чего-то в это синктасисе не догоняю!Пиши точнее, я то типа - "У меня машина не хочет заводится.Не подскажете в чем проблема?" :-) Счачтливо! Ответ отправлен: 14.05.2003, 16:35 Отправитель: BOLT
Вопрос № 765
Как можно убить статическую переменную, когда она уже не нужна? Спасибо!
Добрый день, Quas! Из моих знаний следует, что это невозможно. Ответ отправлен: 13.05.2003, 22:03 Отправитель: BOLT Отвечает Shurik
Здравствуйте, Quas! Используйте динамическую или указатель на функцию с ее использованием
Ответ отправлен: 16.05.2003, 16:22 Отправитель: Shurik Отвечает Pin
Добрый день, Quas! Никак, на то она и статическая. Ответ отправлен: 14.05.2003, 00:06 Отправитель: Pin Отвечает vitya
Здравствуйте, Quas! Увы никак. В лучшем случае ты можешь создать статический указатель, а потом его delete тогда всего-лишь 4 байта у тебя будет занято памяти. Ответ отправлен: 14.05.2003, 08:33 Отправитель: vitya Отвечает Yuri Gordienko
Доброе время суток, Quas! Никак, на то она и статическая. Под словом "убить" я понимаю освободить занимаемую переменной память. Удачи
Ответ отправлен: 14.05.2003, 10:23 Отправитель: Yuri Gordienko Отвечает Avl2k
Добрый день, Quas! Статические переменные убиваются автоматически при завершении программы. Если в Вашей программе наступает момент, когда переменная не нужна, значит по смыслу она не является статической и надо несколько перепроектировать код, например передавать ее параметром. С уважением, Avl2k. Ответ отправлен: 14.05.2003, 10:54 Отправитель: Avl2k Отвечает Ramzes
Добрый день, Quas! Никак. Статические переменные "живут" в области для глобальных переменных. Ответ отправлен: 14.05.2003, 12:12 Отправитель: Ramzes
Вопрос № 766
Здраствуйте. Подскажите пожалуйста: Как с помощью WinApi добратьсь до эл-та меню и сделать его например CHECKED. Т.е не в rc файле, а программно.
Здравствуйте ув. Эксперты! ОС Win Xp Нужно перевести время на 1 час назад. Пишу SYSTEMTIME s,d; GetSystemTime(&d) s.wHour=d.wHour-1; SetSystemTime(&s); Но время не переводится Почем? p.s. Уймите Knignika а то он без году неделя эксперт а уже грубить начинает.
Приветствую Вас, m0v8lack! Если в 9X работает, а в XP - нет, могу предположить, что это связано с привилегиями. Конкретно с SE_SYSTEMTIME_NAME, по дефолту она не установлена, ее можно установить с помощью AdjustTokenPrivileges(). Кстати, кому я нагрубил? Вроде ничего обидного не писал? Уточните, пожалуйста, мылом - я извинюсь.
Ответ отправлен: 14.05.2003, 08:31 Отправитель: Knignick Отвечает Yuri Gordienko
Добрый день, m0v8lack! Возможно, у Вас нет привилегий изменять время. Но по приведенному примеру видно, что структура s содержит полный мусор, кроме часов(если я не ошибаюсь, то функция SetSystemTime контролирует корректность значений параметров). Поэтому уберите s вообще, а часы изменяйте на структуре d. А вообще, правильнее сначала проверять привилегии на подобные системные действия. Удачи
Ответ отправлен: 14.05.2003, 10:20 Отправитель: Yuri Gordienko Отвечает Avl2k
Здравствуйте, m0v8lack! По идее должно работать. Возможно у того account'а, под которым вы запускаете программу, нет прав на перевод системного времени. Точнее можно узнать так: убедиться, что SetSystemTime вернула 0 и посмотреть код ошибки GetLastError() в разделе MSDN "Win32 Error Codes" (или прямо в MSDEV через QuickWatch, набрав в качестве выражения "код,hr" без кавычек. С уважением, Avl2k. Ответ отправлен: 14.05.2003, 10:47 Отправитель: Avl2k Отвечает Andrew Vext
Доброе время суток, m0v8lack! Попробуйте проверить права учетной записи из-под которой выполняется программа (есть ли право изменять системное время). Ответ отправлен: 14.05.2003, 11:59 Отправитель: Andrew Vext Отвечает Hayk
Здравствуйте, m0v8lack! Otsutstvuyet inicializaciya strukturi "s". Strukturu "d" inicializirovala funkciya GetSystemTime, a kto doljen delat' eto dlya "d" ? U tebya tam v polyax chert ego znayet chto tvoritsya ... vot i ne rabotayet. Ответ отправлен: 14.05.2003, 12:12 Отправитель: Hayk Отвечает xiron
Здравствуйте, m0v8lack! Дело в том что ты используеш 2 переменные SYSTEMTIME s,d в d записываеш GetSystemTime(&d) s.wHour=d.wHour-1; меняеш только поле wHour и не копируеш другие поля. А вообще то можно было бы обойтись и ондной переменной. SYSTEMTIME time; GetSystemTime(&time); time.wHour = time.wHour - 1; SetSystemTime(&time); Ответ отправлен: 14.05.2003, 16:43 Отправитель: xiron Отвечает BOLT
Доброе время суток, m0v8lack! Э такая фишка в Windows-NT based не катит.Ты наверное использушь Windows2000/XP.Но, как говорил...не помню кто - не все потеряно: Использую api-функцию для смены системных привелегий BOOL AdjustTokenPrivileges( HANDLE TokenHandle, privileges BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength ); Меняешь время, потом ставишь привелегия наместо! Вот и все. Счастливо, друг! Ответ отправлен: 14.05.2003, 22:35 Отправитель: BOLT
Форма отправки вопроса
Внимание!
Мы рекомендуем открывать рассылку в программе Internet Explorer 5.0+
или отправлять вопросы с сайта по адресу:
http://rusfaq.ru/cgi-bin/Message.cgi.