Блог gunsmoker-а (переклади) чому повернені значення-дескриптори так непослідовні

Чому повернені значення-дескриптори так непослідовні?

Чому ж повернені значення так відрізняються?

Причини, як ви вже підозрюєте, - історичні.

Ці значення вибиралися, виходячи з міркувань сумісності з 16-ти бітної Windows. 16-ти бітні функції OpenFile, _lopen і _lcreat повертали -1 при помилці, тому 32-х розрядна функція CreateFile також повертає -1 (INVALID_HANDLE_VALUE), щоб спростити перенесення додатків з Win16.

(Збройні цим знанням, ви вже можете відповісти на таке просте питання: чому, коли мені потрібно викликати CreateFile, хоча в дійсності я не відкриваю файл? Хіба не повинна функція називатися OpenFile? Відповідь: так, OpenFile було б більш підходящим ім'ям, але це ім'я вже зайнято.)

З іншого боку, в Win16 не було еквівалентів для CreateThread або CreateMutex, тому вони повертають 0.

Оскільки прецедент уже встановив непослідовність значень, що повертаються, то при додаванні нової функції завжди виходить вибір між поверненням 0 або INVALID_HANDLE_VALUE.

Ця непослідовність має кілька наслідків.

За-перше, звичайно ж, вам потрібно акуратно перевіряти повернені значення.

По-друге. це означає, що якщо ви хочете написати якусь загальну обгортку навколо значення дескриптора - то вам треба розрізняти два можливих значення "дескриптор".

По-третє, якщо ви хочете форматувати значення дескриптора, то вам доведеться робити це по-різному, в залежності від функції, з якою ви зібралися його використовувати. Наприклад, наступний код невірний:
У цьому коді два бага. По-перше, що повертається з CreateFile значення перевіряється невірно. Код вище перевіряє на 0 замість INVALID_HANDLE_VALUE. По-друге, код невірно инициализирует змінну H. Ось виправлений варіант:
По-четверте, вам потрібно бути особливо уважними зі значенням INVALID_HANDLE_VALUE: чисто випадково воно збігається зі значенням псевдо-дескриптора, що повертається GetCurrentProcess. Багато функцій ядра приймають такі псевдо-дескриптори, тому, якщо ви, наприклад, облажався і випадково викличте, скажімо, WaitForSingleObject зі значенням INVALID_HANDLE_VALUE, в результаті ви виявите, що ви чекаєте поточний процес. Таке очікування, звичайно ж, ніколи не завершиться, тому що процес переходить в сигнальний стан тільки при виході, тому ви в підсумку чекаєте самого себе.

Схожі статті