Cppcoreguidelines: Avoid iostream and cstdio

Created on 9 Mar 2020  路  16Comments  路  Source: isocpp/CppCoreGuidelines

They are harmful, slow and insecure.

declined

Most helpful comment

You should know that these rants just make everybody want to ignore you, even if some of your points are valid.

I'm unsubscribing from updates to this ticket.

All 16 comments

As In.0 puts it,

We are uncomfortable with rules that simply state "don't do that!" without offering an alternative.

what's your alternative?

Note also http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slio3-prefer-iostreams-for-io

Wrong. They should be both avoided since iostream is usually implemented by stdio.h so technically you are still using stdio.h. (GCC, clang, and VC they all implement iostream with stdio.h) The worse part is that no portable way exists to get file descriptor and win32 handle from fstream which is a huge issue. https://www.ginac.de/~kreckel/fileno/

Both iostream and stdio.h and charconv are slow as fuck. I can easily defeat them with 20 times faster since I can do with zero copy I/O, memory map, static manip, syscall instructions directly, no virtual function calls, no RTTI, no locale, no ctype.h, no FILE*, no unget/unput, no runtime format parsing, no extra binary artifacts, in place formating, no locking, compile time table generation and inline everything. C++20 fmt does not save you at all since none of these issues are actually solved.

Stupid designs like std::endl and abusing operator overloading are other design issues that cannot be dealing with since it will break backward compatiblity. It cannot do stuffs like exploiting atomicity of syscall which creates process safety issue.

iostream does not immue to TOCTTOU and you cannot add O_NOFOLLOW, O_CLOSEXEC flags like POSIX do which means theoretically any fstream open could be a privilege boost and override your /etc/passwd.
And unlike FILE* where you can use fdopen with POSIX standard to construct one, you cannot do that with iostream. You can neither use directory handle to construct fstream to avoid TOCTTOU and even the std::filesystem has a compatibility issue with ofstream. C++17 charconv and filesystem are HUGE mistakes and will finally face their ends like std::regex is now facing.
iostream's virtual inheritance graph is a long term issue of C++.
Not considering std::locale and facet are just another abominations.

BTW, you can use neither stdio.h nor iostream in a freestanding environment due to the huge amount of useless dependencies on C runtime, then people start to create their own ones which cause more damage to the language. C++ Exceptions also rely on stdio.h and exceptions require I/O at its termination. That is another oddity of C++ exceptions. That is one reason why exceptions are largely banned besides it violates the zero-overhead principle. Neither herbception solves these issues.

The solution is to revamp the C++ io system in the future along with deterministic exceptions and deprecate iostream and FILE*. Also, we need to deprecate charconv, fmt, filesystem, network, LLFIO, process, boost iostreams all these IO libraries who just do the same thing and iostream and stdio.h do and they have a compatibility issue. There is a reason why iostream is largely banned like exceptions and RTTI.
https://bitbucket.org/ejsvifq_mabmip/fast_io

We need to do more than this. Like how to fix C++ abstract machines to understand pages and virtual memory space. Unfortunately, I/O is the central part of process communications since pipes are extremely important.

iostream is another issue that DESPERATELY needs to be solved like herbception does to the C++ exceptions.

My point with http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slio3-prefer-iostreams-for-io was merely that a rule already exists addressing your concern. Maybe it's right. Maybe it's wrong but it's a relevant read for anyone concerned with this issue. If something were to change as a result of this issue it would be that rule.

Unfortunately I think I distracted you from @cubbimew's more relevant question: what's your alternative?

Keep in mind, rewriting iostream, charconv, fmt, filesystem, network, LLFIO, proces and boost iostreams is not practical advice to give to a c++17 programmer who is the target audience for theses guidelines.

Keep in mind, rewriting iostream, charconv, fmt, filesystem, network, LLFIO, proces and boost iostreams is not practical advice to give to a c++17 programmer who is the target audience for theses guidelines.

That should be exactly the priority of the language now. Make a new plan to deprecate all of them and revamp a new one. Or the language will die since this trend of creating N+1 problem starting from charconv and filesystem is just problematic. Just like boost expected, boost outcome do to the exception model.

std::to_chars and std::from_chars for long double do not have algorithms for satisfying all their requirements. microsoft's STL assumes long double to be 64 bits long while long double in GCC is 128 bits. Ryu does not provide algorithms for fully long double support. std::from_chars is even worse since it requires to bring dependencies on multi-precision libraries currently. They do not worth the time and effort for library implementors to implement them and that is why charconv for floating point are not available for libstdc++ and libc++. charconv should be removed from the standard.

People (like LLVM does) who banned iostream should be legalized. They have legitimate reasons to ban them.

"Keep in mind, rewriting iostream, charconv, fmt, filesystem, network, LLFIO, proces and boost iostreams is not practical advice to give to a c++17 programmer who is the target audience for theses guidelines."
charconv, fmt, filesystem, network, LLFIO, proces and boost iostreams should be avoided at ALL cost.

ASIO library just bloats binary compared to directly wrap POSIX apis with RAII. (Even a sync echo chamber could be to 10MB with static compilation by using ASIO library)

It's very hard to take you seriously with phrases like abomination used to describe facilities used by most C++ programs, without problems.

You're commenting on guidelines for the current language. This is neither a place for asking other people to write the proposal you so desperately want written, nor is it a place for pitching your own libraries. This is just unnecessary noise for people watching this repository.

It's very hard to take you seriously with phrases like abomination used to describe facilities used by most C++ programs, without problems.

You do not take this seriously since you have used abominations for so long just like C programmers do not realize error code is security issue. I have serious discussions with a lot of people in the real-world and they completely agree with me. C++ iostream is error code in C. It pollutes every code and community it touches. I used to make same mistakes on exceptions. Thanks, Herb Sutter for pointing out the issues of C++ exceptions. Unfortunately, iostream is the same pattern.

They do have problems. return-to-libc, type-confusion, TOCTTOU security vulnerabilities are examples of how problematic C and C++ runtimes are. Unfortunately, iostream has all these vulnerabilities. I have seen security people just do research on C++ iostream virtual inheritance graph because it is an exploitable security attack surface.

We could have a serious skype talk on this topic since I believe C++ is going the terribly wrong direction.

Herbception should be prioritized for everything else. C++23 network library needs to be further delayed. Add herbception and contract in C++23. Other stuffs should be furtherly postponed.

In cppcon2019, herb sutter proposed std::down_cast for base to derived fast casting. iostream is not the case since it relies on virtual inheritance. std::down_cast only works when you do not go across the virtual inheritance link. What that means is that RTTI will NEVER be able to be deprecated or removed from the language. And I/O is the number one producer of exceptions, do you see the patterns here? If we do not fix I/O, we can neither fix exceptions nor RTTI.

You're commenting on guidelines for the current language. This is neither a place for asking other people to write the proposal you so desperately want written, nor is it a place for pitching your own libraries. This is just unnecessary noise for people watching this repository.

Just do not use iostream tbh. Write your own one and wrap POSIX apis with RAII + exceptions. Or you have troubles dealing with native APIs.

LLVM coding standard. Do not use iostream
https://llvm.org/docs/CodingStandards.html#id48

BTW, libstdc++'s random_device is implemented with FILE* not fstream. Even the standard library does not use it, why do you use it?

Some of that article is so stupid it makes my head hurt.

most of the C++ methods are explicitly mapped to the GLIBC C-functions

when looking at a function that just extracts an integer from a time_point and returns it as a time_t. There are no "GLIBC C-functions" there at all, he got confused by a code comment.

Do you have anything constructive for the guidelines, or just more of the same hyperbole?

Some of that article is so stupid it makes my head hurt.

most of the C++ methods are explicitly mapped to the GLIBC C-functions

when looking at a function that just extracts an integer from a time_point and returns it as a time_t. There are no "GLIBC C-functions" there at all, he got confused by a code comment.

Do you have anything constructive for the guidelines, or just more of the same hyperbole?

"And third, now() just makes a dumb call to clock_gettime(). Another compiler path, depending on system, would call gettimeofday(). I removed several of these #ifdefs for clarity."

He is exactly right.

That is a very true fact so-called C++ standard library that just usually wraps libc functions. stdio_filebuf for example.

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/ext/stdio_filebuf.h

These are all the different levels of hacks I did to stream. Hack its internal FILE, construct stream from FILE cross platforms to support legacy C++ toxic stream code base. It is totally a pain.
If the C++ standard library never provides more facilities, instead they use libc as implementation, why bother using them? The attack surface of return-to-libc is still there. ASLR does not save you.

https://github.com/expnkx/fast_io/blob/master/include/fast_io_legacy_impl/stream_file.h
https://github.com/expnkx/fast_io/blob/master/include/fast_io_legacy_impl/filebuf_handle.h

As this guy pointed out 15 years ago. Sadly, nothing really changes in 15 years.
https://www.ginac.de/~kreckel/fileno/

error "Does anybody know how to fetch the bloody file descriptor?"

return stream.rdbuf()->fd();  // Maybe a good start?

endif

Here is another example of why C++ iostream sucks. Protected methods and private data members are OBJECTIVELY harmful. getting fd will cause UBsanitizers to complain. Like I said before, iostream encourages type confusion. Itself is a bug. iostream = type confusion.
https://github.com/google/sanitizers/issues/1203

DON'T USE IOSTREAM, IOSTREAM ====== UB ==== BUG!!!.

iostream = binary bloat. AVOID IT AS PLAGUE IF YOU WANT PERFORMANCE AND SMALLER BINARY SIZE.
#iostreamharmful

You should know that these rants just make everybody want to ignore you, even if some of your points are valid.

I'm unsubscribing from updates to this ticket.

Was this page helpful?
0 / 5 - 0 ratings