Pull to refresh

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

Reading time 2 min
Views 2.6K
Development for Windows *
Translation
Если в документации сказано, что вы должны вызвать функцию, значит, вы должны. Возможно, функция ничего не делает, но это не значит, что она ничего не будет делать в будущем.

Сегодняшний пример — функция GetEnvironmentStrings, которая возвращает все переменные окружения текущего процесса в одном блоке для изучения на досуге. Когда вы с этим закончите, предполагается, что вы используете FreeEnvironmentStrings. Так сказано в документации, и если вы это сделаете — вы в порядке (you're in good shape).
Читать дальше →
Total votes 64: ↑58 and ↓6 +52
Comments 29

ERRORLEVEL это не %ERRORLEVEL%

Reading time 2 min
Views 93K
Development for Windows *
Translation
У командный процессора cmd.exe есть такая вещь — уровень ошибки (error level). Это код выхода (exit code) программы, которую вы запускали последней. Проверить уровень ошибки можно при помощи команды IF ERRORLEVEL.
Читать дальше →
Total votes 22: ↑17 and ↓5 +12
Comments 10

Следствие алгоритма планировщика: низкоприоритетные нити могут занять 100% CPU

Reading time 1 min
Views 945
Development for Windows *
Translation
Время от времени я вижу вариации на этот вопрос. «Почему моя низкоприоритетная нить съедает 100% CPU?»

Установка низкого приоритета не означает, что тред будет потреблять мало CPU. Это всего лишь означает, что он не будет получать процессорного времени, пока есть готовые к исполнению нити с более высоким приоритетом. Но если у вас сделано так, что ваш поток единственный, готовый к выполнению, тогда он получит весь процессор.

Приоритет просто контролирует, какая нить получит первые фишки процессорного времени, но если вы устраиваете так, что ваша нить только одна, кто хочет запуститься, тогда она получит весь процессор. Курица, низшая по порядку клевания съедает всё, что ей захочется, если нет более высокоранговых куриц вокруг. Вы заплатили за этот процессор. Нет причин злобно отказывать в нём.

UPD: всем спасибо за карму. перенес в специализированный блог.
Total votes 19: ↑11 and ↓8 +3
Comments 10

Как мне узнать, что каталог на самом деле — Корзина?

Reading time 2 min
Views 2.2K
Development for Windows *
Translation
Вот вопрос, вызванный реальным запросом клиента:

Мне нужна функция, которая по пути определяет, является ли это частью Корзины. Я пробовал использовать SHGetSpecialFolderPath с CSIDL_BITBUCKET, но это не работает, потому что Корзина — виртуальный каталог, который является объединением Корзин со всех дисков.

Читать дальше →
Total votes 11: ↑7 and ↓4 +3
Comments 12

Как безопасно доставить SIGINT в главный поток?

Reading time 2 min
Views 872
Development for Windows *
Translation
Комментатор AnotherMatt удивляется, почему консольные Win32 приложения доставляют сообщения в другой поток. Почему они не посылают их главному потоку?

На самом деле, у меня обратный вопрос. Почему в UNIX сигнал посылается главному потоку? Это делает практически невозможным сделать что-нибудь важное внутри обработчика сигнала. Главный поток может быть внутри менеджера кучи (удерживать критическую секцию) во время приёма сигнала. Если обработчик сигнала попытается получить доступ к куче, то произойдет взаимная блокировка с самим собой, если вам повезёт. В худшем варианте повредится куча.
Читать дальше →
Total votes 7: ↑5 and ↓2 +3
Comments 5

Почему некоторые называют область уведомлений «треем»?

Reading time 3 min
Views 13K
Interfaces *
Translation
оригинал опубликован в 2003, и относится к интерфейсу Windows XP

Короткий ответ: потому что заблуждаются.

Длинный ответ: официальное название штуковины снизу экрана — «панель задач» (taskbar). Она состоит из нескольких элементов — кнопка «Пуск», кнопки переключения между задачами, часы, и «область уведомлений» (taskbar notification area).

Распространённая ошибка — называть область уведомлений «треем» (или даже «системным лотком»). Она никогда так не называлась. Если вы встретите в документации упоминание «system tray», можете доложить, что обнаружили ошибку.

Откуда взялось это неверное название?

В ранних версиях Chicago — ещё до того, как проект получил название Windows 95 — панель задач была не панелью задач, а папкой, зафиксированной снизу экрана. Она была всегда на виду, и можно было «бросать» в неё документы и ярлыки для быстрого доступа — аналогично лотку для всякой всячины, который ставят в верхний ящик письменного стола.



Оттуда и взялось название «лоток (tray) рабочего стола». Немного сомнительное продолжение метафоры «рабочего стола на экране» — но всё ещё в пределах здравого смысла. (Вот если бы вместо обоев на стол клали скатерть...)

Читать дальше →
Total votes 208: ↑170 and ↓38 +132
Comments 148

Байки о несовместимых приложениях

Reading time 7 min
Views 10K
Development for Windows *
Translation
Это отрывки из бесплатной главы из бумажной книги «The Old New Thing». Они ничему не пытаются научить; это просто короткие забавные эпизоды из будней борцов за совместимость новых версий Windows со старыми приложениями.

Изменяем номер версии Windows


Изменить номер версии, который Windows сообщает программам, не просто, как кажется. Например, некоторые программы проверяют номер версии так:
UINT Ver = GetVersion();
UINT MajorVersion = LOBYTE(uVer);
UINT MinorVersion = HIBYTE(uVer);
if (MajorVersion < 3 || MinorVersion < 10) {
    Error("This program requires Windows 3.1");
}

Представьте себе, как этот код отработает на Windows 95, у которой номер версии 4.0. Вторая проверка срабатывает из-за того, что 0 меньше 10.
И ладно бы программа просто выводила сообщение об ошибке и завершалась. Многие рушились: очевидно было, что их поведение на «неподдерживаемых» версиях Windows никогда не тестировалось.

Таких программ оказалось настолько много, что мы перестали исправлять их по одной, и просто изменили возвращаемый номер версии с 4.0 на 3.95.

Программы для MS-DOS тоже не все гладко реагировали на изменение версии ОС. Это удивительно потому, что к тому времени у MS-DOS уже были десятки выпущенных версий и под-версий, и разработчикам пора было бы уже научиться проверять номер версии. Но например, один пакет программ использовал номер версии DOS как индекс в таблице функций: по собственной функции для каждой вышедшей версии. В таблице было пять функций: от MS-DOS 1.x до 5.x. Когда программа запускалась под MS-DOS 6.0, она вызывала адрес за пределами таблицы, и рушилась.

Изменить номер версии, который Windows сообщает программам, — необходимый, но очень тяжёлый шаг. Пара нажатых клавиш, и падают сотни приложений, отлично работавших до сих пор; теперь отделу совместимости придётся потратить на вылавливание чужих багов лишнюю тысячу человеко-часов.

Читать дальше →
Total votes 147: ↑140 and ↓7 +133
Comments 144

Смерть OS/2

Reading time 3 min
Views 8.4K
History of IT Software
В обсуждении Windows 3.1 на прошлой неделе danSamara упомянул:
Ваша сложная и многогранная система работала у меня в виртуальной машине из под OS/2, которая уже тогда была по настоящему 32-разрядной и многозадачной, а ваша суровая многогранная правда выглядела убого и неказисто.

Как же так вышло, что убогая и неказистая Windows задушила мощную и совершенную OS/2?
Рассказывают разработчики:

Рэймонд Чен: «убойной прогой» для Windows 1.0 — той, ради которой люди готовы были купить новую ОС, — был Adobe PageMaker. Потом появился ещё и Excel.

Ларри Остерман: на самом деле, Pagemaker и Excel были «убойными прогами» для MacIntosh; уже впоследствии их выпустили и для Windows.

Насколько я помню, под Windows вообще не было «убойных прог». Windows 1.0 и 1.1 продавались скромными тиражами по паре тысяч копий в месяц. Windows 386 (версия 2.0) продавалась лучше, потому что позволяла запускать одновременно несколько DOS-приложений. Не любые приложения можно было запускать одновременно; фактически, едва ли можно было запустить что-то более сложное, чем несколько копий GWBasic.

Всё поменялось, когда вышла Windows 3.0.
Читать дальше →
Total votes 119: ↑110 and ↓9 +101
Comments 133

Как звали Доктора Ватсона?

Reading time 2 min
Views 3.1K
Development for Windows *
Translation
Многие помнят программу «Dr.Watson», появившуюся в бета-версии Windows 3.0, и живую до сих пор — правда, уже под названием «Windows Error Reporting». В своём исходном варианте Dr.Watson записывал в лог-файл данные об ошибках в программах, чтобы этот файл можно было приложить к баг-репорту. Значком Dr.Watson был дружелюбный доктор со стетоскопом.



Большинству неизвестно, что вначале эта программа называлась иначе.
Читать дальше →
Total votes 116: ↑105 and ↓11 +94
Comments 24

В чём различие между папками Windows и System?

Reading time 3 min
Views 4.7K
Development for Windows *
Translation
(Windows была выпущена 20 ноября 1985. Сегодня ей исполняется 25. С днём рождения!)

В Windows API с самого начала есть две отдельные функции GetWindowsDirectory и GetSystemDirectory. Почему недостаточно было одной? Обе эти системные папки защищены от записи, обе входят в PATH и в список поиска DLL-библиотек. Зачем было их разделять?

Аксакалы вспомнят, что в те давние времена назначение этих папок различалось. Папка Windows была доступна для записи, и именно в ней хранились все настройки пользователя. Например, функция GetProfileInt читает из файла WIN.INI в папке Windows, и функция GetPrivateProfileInt, если не указан полный путь INI-файла, по умолчанию работает с папкой Windows.
В те давние времена не было отдельных папок с профилями пользователей; в папке Windows, по сути, хранился профиль единственного пользователя в системе.

С другой стороны, большинство системных файлов Windows хранилось в папке System, и эта папка использовалась только для чтения. Даже если не было механизма, фактически запрещавшего запись в эту папку, — сама Windows никогда в неё не писала (исключая установку и удаление приложений, и прочие операции по настройке системы).

Разделение системных файлов на две папки позволяло Windows работать в нескольких различных конфигурациях.
Читать дальше →
Total votes 138: ↑113 and ↓25 +88
Comments 112

ZOMG! Эта программа загружает процессор на 100% !!1!

Reading time 3 min
Views 20K
Development for Windows *
Translation
Непонятно, почему люди относятся к программам, загружающим процессор на 100%, так, как будто эти программы без конца пинают беззащитных маленьких щенят. Им кажется, что столбец в Диспетчере задач — это счётчик: сколько щенят в секунду пинает программа.

Успокойтесь. Если программа загружает процессор на 100% и ничего при этом не делает, то, пожалуй, её можно отнести к бесстыдным пинателям щенят. Но если программа работает, и использует все 100% для своей работы, — то её, наоборот, стоит похвалить за эффективную работу!

Представьте себе: пусть нагрузка вашего процессора никогда не превышала бы 50%. Выходит, вы используете компьютер лишь наполовину; не значит ли это, что вы просто переплатили за него двойную цену? Задача, которая выполнилась бы за пять минут при полной загрузке, выполняется у вас за десять минут; но зато драгоценный индикатор загрузки никогда не переходит воображаемую «красную черту». (Обратите внимание: в Windows на этом индикаторе нет никакой красной черты.)

Например, один программист спрашивал, как изменить программу, чтобы она меньше загружала процессор, но при этом выполняла работу «за разумное время». Чего ради уменьшать загрузку? Почему вместо того, чтобы закончить работу как можно быстрее, — программа должна беспокоиться о циферках в Диспетчере задач?

Если бы вы заведовали банком, в котором работают десять клерков, и туда ломилась бы толпа посетителей, — вы бы впустили их, чтобы все десять клерков работали, или оставили бы посетителей ждать в очереди, чтобы загружать клерков не более чем наполовину?

Когда конец кончал бы все, -- как просто! Все кончить сразу!
Total votes 126: ↑70 and ↓56 +14
Comments 119

Windows Confidential: То, что сохранилось из Windows 3.0

Reading time 5 min
Views 4.2K
Development for Windows *
Translation
«Если я системными политиками запрещаю значки на рабочем столе, то от двойного щелчка по нему начинает запускаться Диспетчер задач. Что за чудеса?»

Это примерно такое же открытие, какое сделал один мой коллега, убравший в своём старом доме декоративные панели, и обнаруживший за ними забытый чулан. В чулане он нашёл несколько раритетов времён Второй мировой войны, включая алкогольный талон с несколькими непробитыми ячейками. Сложно представить, что чувствовал владелец талона, забывший его в чулане.

Чулан, скрытый за рабочим столом Windows, — это Диспетчер программ, оставшийся со времён Windows 3.0. Диспетчер программ позволял запускать приложения, но не позволял переключаться между ними: в нём не было аналога панели задач, отображавшей все запущенные приложения. Чтобы увидеть список открытых окон, пользователь запускал Диспетчер задач — горячей клавишей Ctrl+Esc, либо двойным щелчком по пустому месту на рабочем столе.



Кроме возможности перейти к любому из открытых окон, Диспетчер задач позволял также закрыть приложения, или упорядочить окна — например, каскадом. Диспетчер задач был единственным местом в Windows, показывавшим открытые окна одновременно: например, Alt+Tab не показывал значки всех окон, как в современных версиях Windows, а переключался между ними по порядку.

Появившаяся в Windows 95 панель задач позволяла видеть все открытые окна и переключаться между ними в любой момент; Диспетчер задач был для этого больше не нужен. Кроме того, свёрнутые окна ложились теперь в панель задач, а не на рабочий стол, как в Windows 3.0. Из места для значков свёрнутых окон, рабочий стол превратился в место для часто используемых ярлыков.

Рабочий стол в Windows 95 — это окно Проводника, растянутое на весь экран, и расположенное ниже окон всех других программ. В этом окне Проводник отображает содержимое папки «Рабочий стол». Но под этим «рабочим столом» остался другой, настоящий рабочий стол,
Изменения вносятся помалу
Total votes 174: ↑169 and ↓5 +164
Comments 117

Управление памятью в реальном режиме Windows

Reading time 6 min
Views 39K
Algorithms *
Недавно Реймонд Чен завершил серию постов, начатую ещё полтора года назад, и посвящённую управлению виртуальной памятью безо всякой поддержки со стороны процессора: Windows до версии 3.0 включительно поддерживала реальный режим 8086. В этом режиме трансляция адреса из «виртуального» (видимого программе) в физический (выдаваемый на системную шину) осуществляется бесхитростным сложением сегмента и смещения — никакой «проверки доступа», никаких «недопустимых адресов». Все адреса доступны всем. При этом в Windows могли одновременно работать несколько программ и не мешать друг другу; Windows могла перемещать их сегменты в памяти, выгружать неиспользуемые, и по мере необходимости подгружать назад, возможно — по другим адресам.

(Интересно, всегдашние холиворщики «это была графическая оболочка, а не операционная система» в курсе об этих её необычайных способностях?)
И как же она ухитрялась?
Total votes 97: ↑91 and ↓6 +85
Comments 33

Что такое -1.#IND и -1.#J?

Reading time 3 min
Views 35K
System Programming *C *
Translation

Любой опытный программист знает, что стандарт представления значений с плавающей точкой (IEEE 754) оставляет несколько зарезервированных значений, соответствующих не-числам (NaN, not-a-number). Стандартная библиотека Visual C печатает не-числа следующим образом:
Печатается Означает
1.#INF Положительная бесконечность
-1.#INF Отрицательная бесконечность
1.#SNAN Положительное сигнальное не-число (signaling NaN)
-1.#SNAN Отрицательное сигнальное не-число (signaling NaN)
1.#QNAN Положительное несигнальное не-число (quiet NaN)
-1.#QNAN Отрицательное несигнальное не-число (quiet NaN)
1.#IND Положительная неопределённость
-1.#IND Отрицательная неопределённость
Положительная и отрицательная бесконечности могут получаться при переполнении в результате арифметического действия — например, при делении на ноль, или при взятии логарифма от положительного нуля. (По стандарту IEEE, любое значение с плавающей точкой имеет определённый знак — не только не-числа существуют в положительном и отрицательном вариантах, но и нулей тоже два.)
Сигнальные и несигнальные не-числа...
Total votes 38: ↑33 and ↓5 +28
Comments 5

Неопределённое поведение и теорема Ферма

Reading time 4 min
Views 51K
Programming *C++ *Compilers *
В соответствии со стандартами C и C++, если выполнение программы приводит к переполнению знаковой целой переменной, или к любому из сотен других «неопределённых действий» (undefined behaviour, UB), то результат выполнения программы может быть любым: она может запостить на Твиттер непристойности, может отформатировать вам диск…
Увы, в действительности «пасхальные яйца», которые бы заставляли программу в случае UB делать что-то из ряда вон выходящее, не встречались со времён GCC 1.17 — та запускала nethack, когда встречала в коде программы неизвестные #pragma. Обычно же результат UB намного скучнее: компилятор просто оптимизирует код для тех случаев, когда UB не происходит, не придавая ни малейшего значения тому, что этот код будет делать в случае UB — ведь стандарт разрешает сделать в этом случае что угодно!
В качестве иллюстрации того, как изобилие UB в стандарте позволяет компилятору выполнять неочевидные оптимизации, Реймонд Чен приводит такой пример кода:

int table[4];
bool exists_in_table(int v)
{
    for (int i = 0; i <= 4; i++) {
        if (table[i] == v) return true;
    }
    return false;
}

В условии цикла мы ошиблись на единицу, поставив <= вместо <. В итоге exists_in_table() либо должна вернуть true на одной из первых четырёх итераций, либо она прочтёт table[4], что является UB, и в этом случае exists_in_table() может сделать всё что угодно — в том числе, вернуть true! В полном соответствии со стандартом, компилятор может соптимизировать код exists_in_table() до
int table[4];
bool exists_in_table(int v)
{
    return true;
}

Такие оптимизации иногда застают программистов врасплох.
Читать дальше →
Total votes 107: ↑104 and ↓3 +101
Comments 129

Если нет разницы между двумя вариантами кода, выбирай тот, который проще отладить

Reading time 2 min
Views 8.2K
Microsoft corporate blog C# *
Translation
В С# существует два способа преобразования объектов: использовать оператор as, который пытается преобразовать объект и в случае успеха возвращает результат, в случае неудачи null; или использовать оператор преобразования.



Какой из этих вариантов выбрать, когда нужно немедленно воспользоваться результатом преобразования?
Читать дальше →
Total votes 33: ↑22 and ↓11 +11
Comments 43

Откуда в Windows взялись функции BEAR, BUNNY и PIGLET?

Reading time 2 min
Views 16K
Development for Windows *History of IT
Translation
Если покопаться в системных файлах Windows 95, там можно было обнаружить недокументированные функции с именами наподобие BEAR35, BUNNY73 и PIGLET12. Откуда взялись эти дурацкие имена?

У них занятная история.
Total votes 37: ↑37 and ↓0 +37
Comments 10