Discussion:
Deprecated POSIX functions ?
(too old to reply)
Timothy Madden
2010-08-29 10:36:37 UTC
Permalink
Hello

I see Visual C++ declares simple POSIX functions like mkdir(), fileno()
as deprecated (since VS 2005), they say, in favor of the ISO C++
conformant _mkdir(), _fileno() !

How can that be ?

First, symbol names starting with an underscore are reserved for use by
the C/C++ implementation, so users should use the standard ones, without
the underscores !

Then, POSIX is a full standard for portable operating systems
interfaces, and the simple file functions there have been reliable since
ever (and the other functions, too). What do they have against it ? What
do they see as wrong with POSIX ?

And also, there are no such things as the ISO C++ conformant names
_mkdir, _fileno, etc. Actually, ISO C++ reserves all names starting with
an underscore, as said, and also does not mention these POSIX functions
at all ! (I have read the latest draft for C++ 0x).

Can anyone tell me what is the Microsoft idea behind this no-POSIX
trend, motivated with the wrong pretense that C++ asks for it ?

Thank you,
Timothy Madden
Bo Persson
2010-08-29 11:33:16 UTC
Permalink
Post by Timothy Madden
Hello
I see Visual C++ declares simple POSIX functions like mkdir(),
fileno() as deprecated (since VS 2005), they say, in favor of the
ISO C++ conformant _mkdir(), _fileno() !
How can that be ?
First, symbol names starting with an underscore are reserved for
use by the C/C++ implementation, so users should use the standard
ones, without the underscores !
Visual C++ isn't claiming to follow the Posix standard, but the C++
standard. There, mkdir() isn't a reserved name, so they shouldn't use
it. On the other hand, _mkdir() is a name the implementation is
allowed to use.

It isn't he functions that are deprecated but the non-conforming
names. :-)
Post by Timothy Madden
Then, POSIX is a full standard for portable operating systems
interfaces, and the simple file functions there have been reliable
since ever (and the other functions, too). What do they have
against it ? What do they see as wrong with POSIX ?
You mean the ability to write programs easily portable to other
operating systems? Hardly a high priority for Microsoft!


Bo Persson
Geoff
2010-08-29 19:04:08 UTC
Permalink
Post by Timothy Madden
First, symbol names starting with an underscore are reserved for use by
the C/C++ implementation, so users should use the standard ones, without
the underscores !
The DEFINITION of names starting with underscore are reserved to the
implementation and user programs should not DEFINE them but it is permissible to
use them if the implementation provides them.

The intent is to create reserved name spaces for implementations and for user
programs to stay out of those name spaces but nothing precludes user programs
from calling those functions if documented and provided.
Timothy Madden
2010-08-29 21:29:48 UTC
Permalink
Post by Geoff
Post by Timothy Madden
First, symbol names starting with an underscore are reserved for use by
the C/C++ implementation, so users should use the standard ones, without
the underscores !
The DEFINITION of names starting with underscore are reserved to the
implementation and user programs should not DEFINE them but it is permissible to
use them if the implementation provides them.
You can use them, but then your code or application will be dependent on
that particular implementation (you lose portability).
Geoff
2010-08-29 21:44:03 UTC
Permalink
Post by Timothy Madden
Post by Geoff
Post by Timothy Madden
First, symbol names starting with an underscore are reserved for use by
the C/C++ implementation, so users should use the standard ones, without
the underscores !
The DEFINITION of names starting with underscore are reserved to the
implementation and user programs should not DEFINE them but it is permissible to
use them if the implementation provides them.
You can use them, but then your code or application will be dependent on
that particular implementation (you lose portability).
No, you lose portability to POSIX compliant implementations. But this is outside
the domain of the Microsoft groups where you posted this question and outside
the domain of Standard C or Standard C++ since POSIX is in neither domain.

#if _MSC_VER > 1500
#define mkdir _mkdir
#endif

OR

#pragma warning (disable:4996) // and cross your fingers
Timothy Madden
2010-08-29 22:18:43 UTC
Permalink
Post by Geoff
Post by Timothy Madden
Post by Geoff
Post by Timothy Madden
First, symbol names starting with an underscore are reserved for use by
the C/C++ implementation, so users should use the standard ones, without
the underscores !
The DEFINITION of names starting with underscore are reserved to the
implementation and user programs should not DEFINE them but it is permissible to
use them if the implementation provides them.
You can use them, but then your code or application will be dependent on
that particular implementation (you lose portability).
No, you lose portability to POSIX compliant implementations.
Yes, that is what I said: I lose portability.

And, as an extra bonus, I now depend on the one C++ implementation that
provides all the names with the underscores.

So why should I use the non-portable names ? How are they better ?

Thank you,
Timothy Madden
Geoff
2010-08-30 03:11:40 UTC
Permalink
Post by Timothy Madden
Post by Geoff
Post by Timothy Madden
Post by Geoff
Post by Timothy Madden
First, symbol names starting with an underscore are reserved for use by
the C/C++ implementation, so users should use the standard ones, without
the underscores !
The DEFINITION of names starting with underscore are reserved to the
implementation and user programs should not DEFINE them but it is permissible to
use them if the implementation provides them.
You can use them, but then your code or application will be dependent on
that particular implementation (you lose portability).
No, you lose portability to POSIX compliant implementations.
Yes, that is what I said: I lose portability.
It's a warning. You don't actually lose anything, your application still
compiles but the function names are deprecated. Microsoft is doing you the great
favor of warning you about the coming changes before it breaks your code.
Post by Timothy Madden
And, as an extra bonus, I now depend on the one C++ implementation that
provides all the names with the underscores.
Why do you think it's only one compiler? Any C99-compliant or modern C++
compiler that pretends to comply with the new standard specification will have
to change. Have you compiled your coded under the latest GCC with -Wall?
Post by Timothy Madden
So why should I use the non-portable names ? How are they better ?
Because the standard says so? The leading underscore denotes implementation
defined functionality that extends beyond the standard and this functionality is
also likely to be system dependent as well. A program that depends on this
extended functionality must be prepared to change as it is ported.
Timothy Madden
2010-08-31 00:47:57 UTC
Permalink
On Mon, 30 Aug 2010 01:18:43 +0300, Timothy Madden
Post by Timothy Madden
On Mon, 30 Aug 2010 00:29:48 +0300, Timothy
Post by Timothy Madden
On Sun, 29 Aug 2010 13:36:37 +0300, Timothy
Post by Timothy Madden
First, symbol names starting with an underscore are reserved for
use by the C/C++ implementation, so users should use the standard
ones, without the underscores !
The DEFINITION of names starting with underscore are reserved to the
implementation and user programs should not DEFINE them but it is
permissible to use them if the implementation provides them.
You can use them, but then your code or application will be dependent
on that particular implementation (you lose portability).
No, you lose portability to POSIX compliant implementations.
Yes, that is what I said: I lose portability.
It's a warning. You don't actually lose anything, your application still
compiles but the function names are deprecated. Microsoft is doing you
the great favor of warning you about the coming changes before it breaks
your code.
Does Microsoft actually intends to /remove/ the POSIX names, for this
pretense that it contravines to ISO C ?
Post by Timothy Madden
And, as an extra bonus, I now depend on the one C++ implementation that
provides all the names with the underscores.
Why do you think it's only one compiler? Any C99-compliant or modern C++
compiler that pretends to comply with the new standard specification
will have to change. Have you compiled your coded under the latest GCC
with -Wall?
I have now, with gcc and with g++ 4.5.0 on Slackware (latest on gcc web
site is 4.5.1), and surprise: no warning with either --pedantic, -Wall,
or both (below is my C++ code).
Post by Timothy Madden
So why should I use the non-portable names ? How are they better ?
Because the standard says so? The leading underscore denotes
implementation defined functionality that extends beyond the standard
and this functionality is also likely to be system dependent as well. A
program that depends on this extended functionality must be prepared to
change as it is ported.
Where does the ISO C or C++ standard says so ? Search the standard, you
will find nothing about deprecating POSIX functions.

And functionality is not system dependent, it is a portable operating
systems interface, and it is not implementation-defined because it is not
defined by the C implementation, it is defined by POSIX and provided by
the POSIX implementation (the operating system).

Thank you,
Timothy Madden

Here is the code sample:

/**
* Uses POSIX stat function on the file name argument
*/

// POSIX/XOpen feature test macros
#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600

#include <cstdlib>
#include <cerrno>
#include <cstring>
#include <ctime>
#include <cstdio>

#include <stdexcept>
#include <iostream>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using namespace std;

int main(int argc, char const *argv[])
try
{
int iRetCode = EXIT_FAILURE;

if (argc != 2)
{
cerr << "Invokes stat (or other) funtion(s) on ";
cerr << "the given argument.\n";
cerr << "Usage:\n";
cerr << "\t" << argv[0] << " filename" << endl;
cerr << endl;
}
else
{
struct stat file_stat;

int iStatCode = stat(argv[1], &file_stat);

if (iStatCode)
{
cerr << "Application error." << endl;
cerr << strerror(errno) << endl;
}
else
{
struct tm file_time;
char szTimestamp[255];

file_time = *localtime(&file_stat.st_mtime);
strftime
(
szTimestamp,
sizeof szTimestamp / sizeof szTimestamp[0],
"%a, %Y-%m-%d %H:%M:%S",
&file_time
);

cout << argv[1] << "\t" << szTimestamp << "\t";
cout << file_stat.st_size << " bytes\n";

FILE *tmp_file = tmpfile();

if (tmp_file)
{
int tmp_fd = fileno(tmp_file);

if (tmp_fd < 0)
{
cerr << "Failed to open temporary file descriptor.\n";
cerr << strerror(errno) << endl;
}
else
cout << "Temporary file descriptor: " << tmp_fd << ".\n";

fclose(tmp_file);
tmp_file = NULL;
iRetCode = EXIT_SUCCESS;
}
else
cerr << "Failed to open temporary file.\n";
}
}

return iRetCode;
}
catch (exception const &ex)
{
cerr << "Application error.\n";
cerr << ex.what() << endl;

return EXIT_FAILURE;
}
catch (...)
{
cerr << "Application error.\n";

return EXIT_FAILURE;
}
Geoff
2010-08-29 20:09:17 UTC
Permalink
Post by Timothy Madden
Then, POSIX is a full standard for portable operating systems
interfaces, and the simple file functions there have been reliable since
ever (and the other functions, too). What do they have against it ? What
do they see as wrong with POSIX ?
And also, there are no such things as the ISO C++ conformant names
_mkdir, _fileno, etc. Actually, ISO C++ reserves all names starting with
an underscore, as said, and also does not mention these POSIX functions
at all ! (I have read the latest draft for C++ 0x).
Can anyone tell me what is the Microsoft idea behind this no-POSIX
trend, motivated with the wrong pretense that C++ asks for it ?
POSIX is not standard C or C++, as your reading of the draft standard indicated.
Some existing POSIX functions may even have some functional defect making them
unsuitable for use in some OS going forward, you don't know. POSIX is a
completely separate standard from C or C++.

Compiler implementers (not just Microsoft) have a choice to make:
Support Standard C - or not.
Support Standard C and POSIX specially.
Support Standard C and deprecate POSIX totally, with or without warning.
Support Standard C and deprecate POSIX name space and warn the user while
providing POSIX functionality within the implementation reserved name space that
the standard allows.

Microsoft chose the latter. They are even free to simply rename the POSIX
functions in terms of the implementation name space. (#define mkdir _mkdir)

You are free to write your code to the C standard and rely on the implementation
space or to disable the warning and hope the future platforms on which your
program will be running will support those deprecated POSIX functions. You are
even free to write your own or grab the POSIX functions and make them part of
your code or even #define mkdir _mkdir in your source but I don't recommend it.
Goran Pusic
2010-08-31 10:34:41 UTC
Permalink
Post by Timothy Madden
Hello
I see Visual C++ declares simple POSIX functions like mkdir(), fileno()
as deprecated (since VS 2005), they say, in favor of the ISO C++
conformant _mkdir(), _fileno() !
How can that be ?
Didnt' everyone miss the boat somewhat?

Here's the state of affairs as I see it: MS realized that they had, in
their CRT (not POSIX, __CRT__), functions like mkdir that were not
standard (that is, they were implementation-specific). So they said,
whoops, that's wrong, we should prepend an '_' there (because
implementations should prepend their own names) and deprecate old
ones. So they did that.

Unfortunately, some of these functions are in POSIX, which you want to
use (in fact, my guess is that MS put them in CRT _because_ they were
in POSIX, and that's their original error). So double whoops, user not
happy! To give unhappy user his POSIX, MS uses #define _POSIX_ (at
least in VC 2008 I have over here).

So... #define _POSIX_ and you're good to go. Normally, with VC++, you
do that in project properties, or you use stdafx.h and put it there.

How's that?

Goran.
Timothy Madden
2010-08-31 15:14:32 UTC
Permalink
Post by Goran Pusic
Post by Timothy Madden
Hello
I see Visual C++ declares simple POSIX functions like mkdir(), fileno()
as deprecated (since VS 2005), they say, in favor of the ISO C++
conformant _mkdir(), _fileno() !
How can that be ?
Didnt' everyone miss the boat somewhat?
Here's the state of affairs as I see it: MS realized that they had, in
their CRT (not POSIX, __CRT__), functions like mkdir that were not
standard (that is, they were implementation-specific). So they said,
whoops, that's wrong, we should prepend an '_' there (because
implementations should prepend their own names) and deprecate old
ones. So they did that.
Unfortunately, some of these functions are in POSIX, which you want to
use (in fact, my guess is that MS put them in CRT _because_ they were
in POSIX, and that's their original error). So double whoops, user not
happy! To give unhappy user his POSIX, MS uses #define _POSIX_ (at
least in VC 2008 I have over here).
So... #define _POSIX_ and you're good to go. Normally, with VC++, you
do that in project properties, or you use stdafx.h and put it there.
How's that?
That would be good. Actually the symbol should be _POSIX_C_SOURCE or
_POSIX_SOURCE, but since they are far from POSIX compliance, the simple
symbol_POSIX_ would also be fine. Unfortunately searching the MSDN site
for it finds nothing but some pasted code samples from VC headers, so
the symbol seems to be undocumented. And if I try to add it to my
project settings then stadafx.cpp no longer compiles.

Indeed I see _mkdir is not in the POSIX header <sys/stat.h> but in
<direct.h>, and so are other POSIX functions in Visual Studio (like
open, creat, pipe, close...). So your explanation has a point and I
appreciate this insight from you. I really though the POSIX functions in
Visual Studio are provided by the POSIX headers, and so it looked
inappropriate for me to change them because of the C standard headers.

But if Visual Studio provides the POSIX headers in the INCLUDE path
anyway, what is wrong with re-declaring the names in their right place
in those headers, so they would no longer be in the CRT ?

That would all the same:
- solve the user names-space intrusion problem for the C
implementation
- keep and improve the little POSIX support that could be
found in Visual Studio
- better keep backward compatibility (as users no longer have
to change the function names throughout their code, but
rather add a few headers at the beginning of the source
files).
I mean their intent and approach is still inappropriate (though now I
understand they might have a better excuse for it than the one in the
MSDN page saying that ISO C++ has deprecated the POSIX names).

And then there are still the functions like stat and fileno, that have
always been in the right header and are not in conflict with the C
implemntation. How is Microsoft deprecating them in order to get them
out of the CRT ?

Thank you,
Timothy Madden

P.S. by chance were <direct.h> and the functions there first introduced
by Borland ?
Goran Pusic
2010-09-01 09:02:54 UTC
Permalink
This post might be inappropriate. Click to display it.
Timothy Madden
2010-09-01 10:47:42 UTC
Permalink
Post by Goran Pusic
Post by Timothy Madden
But if Visual Studio provides the POSIX headers in the INCLUDE path
anyway, what is wrong with re-declaring the names in their right place
in those headers, so they would no longer be in the CRT ?
- solve the user names-space intrusion problem for the C
implementation
- keep and improve the little POSIX support that could be
found in Visual Studio
- better keep backward compatibility (as users no longer have
to change the function names throughout their code, but
rather add a few headers at the beginning of the source
files).
Yes, that looks coherent to me.
Thank you ! At last, someone else can see my point and understands it ! :)
Post by Goran Pusic
Post by Timothy Madden
And then there are still the functions like stat and fileno, that have
always been in the right header and are not in conflict with the C
implemntation. How is Microsoft deprecating them in order to get them
out of the CRT ?
The key issue (by my guess as to what was happening in MS) is these
are not part of CRT, hence they are deprecated (I could be wrong, but
my copy of C99 hasn't got either stat, nor fileno). So it could be
that POSIX and CRT really are at odds? (I don't know nor care much,
but it seems so). In case of e.g. fileno, it looks like POSIX pollutes
CRT, and on top of that, if it's included in vendor's CRT, it should
have that pesky '_'. It's kinda lose/lose situation.
Actually I can see now that it is just an undocumented /win/ situation.

The point is <sys/fstat.h> is a POSIX-only header (and not an ISO C
header). So the stat() and fstat() functions there are provided by the
POSIX implementation not the C implementation. As such, there is no need
to deprecate them to get C conformance. They can just stay there.

By the same reasoning, <stdio.h> is both a POSIX header and C header,
but the fileno() function there is still a POSIX-only function, and as
such there is no need to deprecate it to achieve C conformance. POSIX
already specifies that fileno only exists if the feature test macro is
defined, and the test macro in turn is an implementation-defined symbol
(because _POSIX_C_SOURCE or _POSIX begin with an underscore), so in the
end it is ISO C conformant.

And to my surprise, this is exactly what Microsoft did: stat() and
fstat() are /not/ being deprecated, as they were already declared in a
POSIX-only header, but are just not documented any more. fileno() has
been deprecated, though, despite being already in the right header. This
could be because they do not implement the test macro _POSIX_C_SOURCE
that would make it visible, but only their specific test macro _POSIX_,
which in turn is not documented.

Also to my surprise, they are implementing the POSIX feature test macro,
too, that declares again all the other POSIX functions (mkdir, open,
read), only it is undocumented (and with a different name). Probably
because the test macro _POSIX_ declares this names still in the wrong
header. If only they could document it and get the ATL headers to comply
with it ...

Knowing about their undocumented _POSIX_ test macro in Visual Studio
really shed light on my view of things, so thank you again for it. Were
did you here or read about _POSIX_ ?

Thank you,
Timothy Madden
Goran Pusic
2010-09-01 11:49:41 UTC
Permalink
This post might be inappropriate. Click to display it.
Timothy Madden
2010-09-01 20:57:14 UTC
Permalink
Post by Goran Pusic
Post by Timothy Madden
Knowing about their undocumented _POSIX_ test macro in Visual Studio
really shed light on my view of things, so thank you again for it. Were
did you here or read about _POSIX_ ?
You prompt me to look. I was shooting off my hip, got lucky (blushes).
(Well, I knew that MS, at least formally, is... ahem, POSIX-
compliant).
Well, trying to actually use the _POSIX_ macro further in my project
shows that it does not do what I think, even if i can now get the ATL
headers to compile with it. :(

I do not understand what it is meant to do, but it looks like _POSIX_
just excludes many non ISO C symbols from the headers ... including
creat() :(

In the end the only way to get the POSIX functions is to define the
documented _CRT_NONSTDC_NO_WARNINGS to disable the warning about
deprecation.

I am getting tired ...

Thank you,
Timothy Madden

Timothy Madden
2010-09-01 10:01:06 UTC
Permalink
Post by Timothy Madden
Post by Goran Pusic
Post by Timothy Madden
Hello
I see Visual C++ declares simple POSIX functions like mkdir(), fileno()
as deprecated (since VS 2005), they say, in favor of the ISO C++
conformant _mkdir(), _fileno() !
How can that be ?
Didnt' everyone miss the boat somewhat?
Here's the state of affairs as I see it: MS realized that they had, in
their CRT (not POSIX, __CRT__), functions like mkdir that were not
standard (that is, they were implementation-specific). So they said,
whoops, that's wrong, we should prepend an '_' there (because
implementations should prepend their own names) and deprecate old
ones. So they did that.
Unfortunately, some of these functions are in POSIX, which you want to
use (in fact, my guess is that MS put them in CRT _because_ they were
in POSIX, and that's their original error). So double whoops, user not
happy! To give unhappy user his POSIX, MS uses #define _POSIX_ (at
least in VC 2008 I have over here).
So... #define _POSIX_ and you're good to go. Normally, with VC++, you
do that in project properties, or you use stdafx.h and put it there.
How's that?
That would be good. Actually the symbol should be _POSIX_C_SOURCE or
_POSIX_SOURCE, but since they are far from POSIX compliance, the simple
symbol_POSIX_ would also be fine. Unfortunately searching the MSDN site
for it finds nothing but some pasted code samples from VC headers, so
the symbol seems to be undocumented. And if I try to add it to my
project settings then stadafx.cpp no longer compiles.
It looks like _POSIX_ macro not only allows the POSIX names to be used
again, but also excludes some implementation-defined symbols from the
headers. The error messages in stdafx.cpp complain that ATL is still
using some of these symbols, so I found that including this code in
stdafx.h immediately after the #include "targetver.h" line would allow a
MFC/ATL application to also be compiled with _POSIX_ and use the POSIX
names:

/*
* Local changes:
* include some headers without the POSIX feature test macro _POSIX_,
* to still get some implementation-specific symbols (_alloca, _malloca,
* _beginthreadex, _gcvt, _wmakepath) used by ATL
*/
#ifdef _MSC_VER
# ifdef _POSIX_
# define PAGEBUILDER_VC_POSIX_FEATURE_TEST _POSIX_
# undef _POSIX_
# endif

# include <stdlib.h>
# include <malloc.h>
# include <process.h>

# ifdef PAGEBUILDER_VC_POSIX_FEATURE_TEST
# define _POSIX_ PAGEBUILDER_VC_POSIX_FEATURE_TEST
# undef PAGEBUILDER_VC_POSIX_FEATURE_TEST
# endif
#endif

just in case anyone else is interested.

Of course including some of the headers with the test macro defined, and
some of them without the test macro defined, would be bad practice (if
not ill-formed if the macro ever gets documented, and gets documented as
"required to be defined before including any headers", the same
_POSIX_C_SOURCE is) but it is here a required workaround and nonetheless
it just works. And malloc.h and process.h are not POSIX headers after
all, so they should not be affected.

Thank you,
Timothy Madden
Loading...