When a stdio stream encounters an error (but not EOF), the stream's error indicator will be set so that ferror() will return nonzero. I have always assumed that more information is available in errno. But how do I know this?
Documentation for some functions [e.g. man fopen under Linux] says that errno will also be set. However man fgets doesn't mention errno at all. The glibc info pages are reassuring:
In addition to setting the error indicator associated with the
stream, the functions that operate on streams also set `errno' in the
same way as the corresponding low-level functions that operate on file
descriptors.
But I have no idea how strong this guarantee is. Is it required by the C standard? What happens in Visual C/C++?
The C Standard itself does not require much use of errno WRT to stdio functions; it specifies ferror() but says of it only that
7.13.10.3 The ferror function The ferror function tests the error indicator for the stream pointed to by stream. The ferror function returns nonzero if and only if the error indicator is set for stream.
from the C99 Draft: http://www.vmunix.com/~gabor/c/draft.html. Any actual error codes used are, for the most part, implementation defined.
However, the GNU C library on linux also conforms to POSIX specifications:
http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm
Which are much more well defined in this context. For example, if you look at the page for fopen:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html
You'll see a lot of detailed information, including specific errno codes, under Errors.
Again, the GNU C library used on virtually all normal linux systems is POSIX compliant, so you can count on that information ;). Those (online) POSIX man pages are also generally more detailed than the standard linux system man pages (read both).
WRT to file operations on other (non-POSIX) platforms, they will have their own implementations. Unfortunately, stuff like that is not transparently portable in standard C. C++ streams do have more standardized error handling, though.
According to the C11 standard, chapter 7.21 ("stdio.h"), only fgetpos, fsetpos and ftell write to errno in the event of an error.
Related
I'm getting a massive speedup from using this option when compiling my code. From the man page it says that this option:
Do not set "errno" after calling math functions that are executed
with a single instruction, e.g., "sqrt"
Its not clear to me what the 'errno' is, and how it is used elsewhere (is this the same as the exit code of a program?) Furthermore, the man page says:
A program that relies on IEEE exceptions for math error handling may
want to use this flag for speed while maintaining IEEE arithmetic
compatibility.
Its not clear to me what this means, are the IEEE exceptions standard for c++ or common libraries of c++ (e.g. Eigen, Boost, etc.)
Essentially, I'm trying to determine if this is a 'safe' option to use in my code, or what side-effects I should be aware of from its use. A previous answer says this may affect 'thread local variables' but I have no clue what that means.
EDIT: My code is a simple one-off procedural code to handle a scientific problem. It is not going to be part of a deeply embeded system that requires complex error-handling. However, the code must not fail in subtle, silent ways.
C introduced the concept of a single errno or "error number" that could be used to determine the precise cause of the failure of some standard functions, including mathematical functions, to perform their duties. POSIX extended errno, and C++11 picked up some of those extensions too.
When one of these functions fails, the global integer errno is set to a value that tells you why. Obviously that incurs a performance penalty.
GCC is saying that this flag disables this behaviour for certain mathematical functions, speeding up your program at the cost of diagnostic utility and standard-compliance.
If you're already not observing errno when any of the affected functions fails, and you're probably not because you'd never heard of it, then you won't lose any functionality. This may be the case if you're writing a really time-constrained program, or when the particular reason for a failure doesn't dictate what your code does next. (However I advise looking into error checking more broadly to ensure that your code is as robust as it ought to be.)
However, it is possible for you to accidentally observe side-effects if you have a bug. Imagine if you were doing something like the following:
std::some_maths_function(42);
if (errno == ERANGE)
exit(-1);
Oops! We are checking errno even when some_maths_function(42) succeeded. Let's say that above this code is a call to std::some_other_maths_function(999) which usually fails and results in errno being set to EDOM. That masked the bug in the code above.
Now turn on the compiler flag. If some_other_maths_function is one of the functions that no longer sets errno, your bug will be unmasked, and it may take you a few moments to realise that you ought to have written something more like:
if (std::some_maths_function(42) == -1)
{
if (errno == RANGE)
exit(-1);
}
Of course it's hardly GCC's fault that you had a bug, but this does show how the behaviour of your program can differ after enabling this "optimisation" flag. Indeed, the documentation says:
This option is not turned on by any -O option since it can result in incorrect output for programs that depend on an exact implementation of IEEE or ISO rules/specifications for math functions. It may, however, yield faster code for programs that do not require the guarantees of these specifications.
In other words, this flag sends you off-book. But it may be worth it.
The variable errno must be thread-local (that is, there is actually one of them for each thread in your program) otherwise it'd be useless in a multi-threaded program. You can research the term "thread-local" for more information on this subject.
Beware that GCC might also disable errno for non-math functions such as malloc when -fno-math-errno is used. [0]
[0] -fno-math-errno causes GCC to consider that malloc does not set errno
In the UCRT signal.h, I see these defines.
#define SIGABRT 22 // abnormal termination triggered by abort call
#define SIGABRT_COMPAT 6 // SIGABRT compatible with other platforms, same as SIGABRT
Full path is c:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt\signal.h if it helps.
In man signal.7 on my Ubuntu 18.04 system I see SIGABRT is also mapped to 6.
This is confusing to me. Being that Windows doesn't truly have "signals" under the hood, and this is all an emulation layer on top of the various messaging mechanisms native to Windows wrapped by the C++11 standard library, why did they choose something non-portable for the default SIGABRT? Do they expect people to be using it as an argument to raise(), or for comparison in a signal handler?
The only documentation I can find regarding the existence of SIGABRT_COMPAT is the comment in the header file, and the table in the online documentation which is no more descriptive than the header.
The standard doesn't even define it: https://en.cppreference.com/w/cpp/header/csignal
I realize that these are all symbolic values and it may be considered poor form to depend on them being specific values (though it can be useful), but this must be here for a reason.
This is a bit upsetting to see because it seems to be there for portability reasons, but at the same time it looks like using it reduces code portability since it's only defined in the UCRT.
In the C++17 filesystem library, we got std::filesystem::remove(path), which — as I understand it — is a direct port of boost::filesystem::remove(path) from Boost.Filesystem.
But C++ inherited from C89 a very similar function called std::remove(path), which is also documented as a way to remove a file from the filesystem. I'm vaguely aware of some pitfalls with this function, e.g. I believe I have heard that on Windows std::remove cannot be used to remove a file that is still being held open by the current process.
Does std::filesystem::remove fix these issues with std::remove? Should I prefer std::filesystem::remove over std::remove? Or is the former just a namespaced synonym for the latter, with the same warts and pitfalls?
The title of my question asks for the difference between boost::filesystem::remove(path) and std::remove(path) because I figure that std::filesystem::remove(path) may not have been implemented by a lot of library vendors yet, but my understanding is that it's supposed to be basically a direct copy of the Boost version. So if you know about Boost.Filesystem on Windows, you probably know enough to answer this question too.
Checking the standard library sources installed with my MSVC, std::experimental::filesystem::remove calls its internal _Unlink helper, which simply calls _wremove, which simply calls Windows DeleteFileW. Similarly, boost::filesystem::remove also just calls DeleteFileW on Windows.
std::filesystem::remove is specified by reference to POSIX remove, but the global wording in [fs.conform.9945] makes clear that implementations are not required to provide the exact POSIX behavior:
Implementations should provide such behavior as it is defined by
POSIX. Implementations shall document any behavior that differs from
the behavior defined by POSIX. Implementations that do not support
exact POSIX behavior should provide behavior as close to POSIX
behavior as is reasonable given the limitations of actual operating
systems and file systems. If an implementation cannot provide any reasonable behavior, the implementation shall report an error as specified in [fs.err.report]. [ Note: [...] ]
Implementations are not required to provide behavior that is not supported by a particular file system. [ Example: [...] ]
Any quirks in ::remove (that is about the actual act of removing rather than identification of the file to be removed) are likely due to limitations of the underlying OS API. I see no reason to think that an implementation of std::filesystem::remove on the same operating system will magically do better.
I have a function which prints some text to an ostream& it receives. I would like to make it adapt to the terminal width, if the ostream targets a terminal, and otherwise default to some value.
What I do right now is the following:
Get an ofstream from the ostream.
Get a FILE* from the ofstream.
Get an integer file descriptor from the FILE*.
Do ioctl(file_descriptor, TIOCGWINSZ, &my_struct_winsize);
with steps 1 and 2 bring due to this SO answer:
Getting a FILE* from a std::fstream
but they are non-portable and GCC-specific (and I'm not sure they'll work for ostreams other than cout/cerr/cin). Can I do better than this?
None of that is gcc-specific. For the rest, TIOCGWINSZ is widely implemented and used with POSIX termios (terminal I/O), although it and the corresponding SIGWINCH are oddly enough not in POSIX. Other methods of getting terminal width (still for POSIX platforms, not generally applicable to Windows):
testing environment variables COLUMNS and LINES (many terminal applications, including those using curses do this, e.g., see use_env, provided by any X/Open curses implementation such as ncurses).
using ECMA-48 cursor position report as done by the resize program.
For Windows, none of that applies. You would get the information from one of the Console API calls such as GetConsoleScreenBufferInfo. Cygwin is a special case, because it runs (more or less) POSIX-like applications which work with the ioctl as well as POSIX terminal I/O. MinGW is lower-level, and does not provide any real extension to the Console API in this area.
Further reading:
get TIOCGWINSZ from <sys/ioctl.h> (clarification on Cygwin mailing list)
signal.h - signals (POSIX: noting absence of SIGWINCH)
ECMA-48,
Control Functions for Coded Character Sets
Microsoft Console Reference
I want to access a text file in a C-like fashion. The option CARRIAGECONTROL= 'NONE' apparently achieves this, according to this page. Is it a standard option ?
If by "C-like fashion" you mean read the file as a stream of bytes, there was no standard way to do this before Fortran 2003. However many compilers offered it as an extension, like the manual of the Intel compiler on the webpage you refered to.
Since Fortran 2003, there is a standard way of opening a file for stream access which is
ACCESS='STREAM'
The standard option is access='stream' in the open statement
In F77, this was not standardized and often compiler dependent.