Почему wxMkDir возвращает 0 при успешном создании каталога?

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

Моя среда — VS 2015 C++, wxWidgets 3.0.2, разработка на Windows 7.

В некотором устаревшем коде вызовы wxMkDir не проверялись на успешность. Согласно документации wxWidgets, wxMkDir имеет возвращаемый тип bool и возвращает true в случае успеха. Однако в случае успеха он возвращает 0.

Почему?


person hlongmore    schedule 10.03.2016    source источник


Ответы (2)


Ответ двоякий: есть две функции с похожими именами, wxMkdir и wxMkDir, с первое задокументировано, а второе не задокументировано. Вторая часть заключается в том, что кажущееся верным предположение, что они будут вести себя одинаково, не является верным предположением.

Недокументированная функция wxMkDir сопоставляется с wxCRT_MkDir, которая, в свою очередь, сопоставляется с wxCRT_MkDirA, а затем с wxPOSIX_IDENT(mkdir), что создает зависящее от платформы имя для упомянутой функции POSIX, mkdir. Согласно документации POSIX для mkdir

После успешного завершения mkdir() возвращает 0. В противном случае возвращается -1, каталог не создается, а errno должен указывать на ошибку.

Итак, условные выражения, такие как:

if (!wxMkDir(newDir)) {
  // handle the error here
}

не получится, но:

if (wxMkDir(newDir) != 0) {
  // handle the error here
}

будет работать так, как ожидалось, в зависимости от того, был ли каталог создан или нет.

Задокументированная функция wxMkdir реализована в исходном файле wx filefn.cpp и использует mkdir, но с условными выражениями, подобными приведенным выше, для сопоставления с соответствующим возвращаемым значением bool.

person hlongmore    schedule 10.03.2016

wxMkdir() и wxMkDir() являются досадными и уродливыми исключениями из общего правила, согласно которому wxWidgets предоставляет wxFoo() оболочку для всех стандартных (имеется в виду либо ANSI C, либо POSIX, поскольку на практике последний является примерно таким же стандартным и более чем C99) функциями, foo() существующими в обоих узкая (char*) и широкая (wchar_t*) версии.

Таким образом, согласно этому общему правилу, вы ожидаете, что wxMkdir() будет вести себя как std::mkdir(), но, к сожалению, wxMkdir() на несколько лет предшествовало Unicode-ификации wxWidgets, и поэтому это правило не могло быть реализовано для него из-за обратной совместимости и других функцию нужно было придумать, чтобы она была просто оболочкой для std::mkdir().

И к настоящему времени, конечно, бремя обратной совместимости стало еще тяжелее, и кажется, что здесь действительно нет ничего разумного, кроме как советовать людям использовать wxFileName::Mkdir(), что однозначно.

</sad-story>

person VZ.    schedule 11.03.2016
comment
Спасибо за информацию. Иногда полезно понять, почему все сложилось так, как оно есть, вместо того, чтобы позволить себе что-то придумать. Таким образом, голосование. :) - person hlongmore; 11.03.2016