Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Одна из неприятных особенностей функции CreateProcess состоит в том, что параметр lpCommandLine должен быть указателем на изменяемые данные. Если вы передадите указатель на память, которая не может быть изменена (например, указатель на страницу, помеченную PAGE_READONLY), то все может повалиться. Комментатор Ritchie удивляется, почему этот параметр такой странный .
Вкратце, кто-то еще в 1980е хотел избежать выделения памяти . (Другая интерпретация этого: кто-то хотел быть черезчур умным.)
CreateProcess временно изменяет строку, переданную в lpCommandLine в попытке разобраться, где кончается имя программы и начинаются параметры командной строки. Функция могла бы снять копию со строки и сделать временные изменения в копии, но! если вы изменяете входную строку непосредственно, то вы экономите дорогостоящую операцию выделения памяти. В старые времена люди старались избегать выделений памяти, так что микро-оптимизации такого рода - это те вещи, о которых люди как правило беспокоились. Конечно, в наши дни, это выглядит достаточно устаревшим.
На самом деле, могут быть и серьезные технические причины (помимо чисто соображений производительности) избегать выделений памяти из кучи. Когда программа валится, отладчик "по месту" запускается функцией CreateProcess, и вы не хотите выделять память из кучи, если причиной краха программы было повреждение кучи. Иначе вы можете получить рекурсивный цикл крахов : пытаясь запустить отладчик, вы валитесь, что означает - вы пытаетесь запустить отладчик для отладки нового краха , что опять валится, и так далее. Первоначальные авторы функции CreateProcess были осторожны в плане избегания выделений памяти из кучи, так что в случае, когда функция вызывается для запуска отладчика, она не споткнется о поврежденную кучу.
Я не уверен, что эти соображения валидны по сей день, но именно эти соображения повлияли на первоначальный дизайн и, таким образом, интерфейс.
Почему затронута только Юникод-версия? Так это потому, что ANSI версия функции просто конвертирует свои строки в Юникод и потом зовет Юникод-версию функции. Таким образом, ANSI-версия функции реализует обход ошибки как побочный эффект своей первоначальной задачи: строка, переданная в Юникод-версию функции - это временная строка!
Упражнение: Почему для ANSI-версии CreateProcess нормально выделять временную строку из кучи, а для Юникодной функции - нет?