简体   繁体   中英

Why does wxMkDir return 0 when successfully creating a directory?

So, I have to admit upfront I already know the answer. I'm asking so others who happen to run into the same problem can find a solution to the problem caused by incorrect documentation.

My environment is VS 2015 C++, wxWidgets 3.0.2, developing on Windows 7.

In some legacy code, calls to wxMkDir were not being checked for success. According to wxWidgets documentation , wxMkDir has a return type of bool, and returns true if successful. However, it returns 0 when successful.

Why?

The answer is two-fold: there are two functions with similar names, wxMkdir and wxMkDir , with the former being documented and the latter not documented. The second part is that the seemingly valid presumption that they will behave the same is not a valid assumption.

The undocumented function wxMkDir maps to wxCRT_MkDir, which in turn maps to wxCRT_MkDirA, then to wxPOSIX_IDENT(mkdir), which creates a platform dependent name for the mentioned POSIX function, mkdir. According to the POSIX documentation for mkdir

Upon successful completion, mkdir() shall return 0. Otherwise, -1 shall be returned, no directory shall be created, and errno shall be set to indicate the error.

So, conditionals like:

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

will fail, but:

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

will work as anticipated based on whether the directory was created or not.

The documented function wxMkdir is implemented in wx source file filefn.cpp, and utilizes mkdir, but with conditionals like the above to map to the appropriate bool return value.

wxMkdir() and wxMkDir() are the unfortunate and ugly exceptions to the general rule that wxWidgets provides wxFoo() wrapper for all standard (meaning either ANSI C or POSIX as, in practice, the latter is about as standard and more so than C99) functions foo() existing in both narrow ( char* ) and wide ( wchar_t* ) versions.

So, according to this general rule, you'd expect wxMkdir() to behave as std::mkdir() but unfortunately wxMkdir() predated, by quite a few years, Unicode-ification of wxWidgets and so this rule couldn't be implemented for it because of backwards compatibility and another function had to be invented to be just a wrapper for std::mkdir() .

And by now, of course, the weight of backwards compatibility is even heavier and there really doesn't seem to be anything reasonable to do here -- other than advising people to use wxFileName::Mkdir() which is unambiguous.

</sad-story>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM