5 ms·
Heh, low comments on C++ posts now. A sign of the times. My two cents anyway. I've been using C++ for a decade. Of all the warts, they all pale in comparison t
by shadowdev1 1y ago
Heh, low comments on C++ posts now. A sign of the times. My two cents anyway.
I've been using C++ for a decade. Of all the warts, they all pale in comparison to the default initialization behavior. After seeing thousands of bugs, the worst have essentially been caused by cascading surprises from initialization UB from newbies. The easiest, simplest fix is simply to default initialize with a value. That's what everyone expects anyway. Use Python mentality here. Make UB initialization an EXPLICIT choice with a keyword. If you want garbage in your variable and you think that's okay for a tiny performance improvement, then you should have to say it with a keyword. Don't just leave it up to some tiny invisible visual detail no one looks at when they skim code (the missing parens). It really is that easy for the language designers. When thinking about backward compatibility... keep in mind that the old code was arguably already broken. There's not a good reason to keep letting it compile. Add a flag for --unsafe-initialization-i-cause-trouble if you really want to keep it.
C++, I still love you. We're still friends.
- juliangmp 1y ago> When thinking about backward compatibility... keep in mind that the old code was arguably already broken. There's not a good reason to keep letting it compile. Oh how I wish the C++ committee and compiler authors would adopt this way of thinking... Sadly we're dealing with an ecosystem where you have to curate your compiler options and also use clang-tidy to avoid even the simplest mistakes :/ Like its insane to me how Wconversion is not the default behavior.
- zahlman 1y ago>Oh how I wish the C++ committee and compiler authors would adopt this way of thinking Many different committees, organizations etc. could benefit, IMO.
- motorest 1y ago> Oh how I wish the C++ committee and compiler authors would adopt this way of thinking... I disagree. If you expect anyone to adopt your new standard revision, the very least you need to do is ensure their code won't break just by flipping s flag. You're talking about production software, many of which has decades worth of commit history, which you simply cannot spend time going through each and every single line of code of your >1M LoC codebase. That's the difference between managing production-grade infrastructure and hobbyist projects.
- johannes1234321 1y agoThe option there is better tooling, for which the foundation exists which can do such maintenance somewhat automatically, in the simplest case by just adding the Keywords to request old behavior. But the annoyance comes when dealing with multiple compilers and versions. Then you have to add more compatibility macros all over. Say, when being a library vendor trying to support broad range of customers.
- motorest 1y ago> The option there is better tooling (...) The tooling already exists. The bulk of the criticism in this thread is clearly made from a position of ignorance. For example, all major compilers already provide flags to enable checks for uninitialized variables being used. Onboarding a static code analysis tool nowadays requires setting a flag in CMake. These discussions would be constructive if those engaging in them had any experience at all with the language and tooling. But no, it seems the goal is to parrot cliches out of ignorance. Complaining that they don't know what a reserved word means and using that as an argument to rewrite software in other languages is somehow something worth stating.
- dwattttt 1y ago> If you expect anyone to adopt your new standard revision, the very least you need to do is ensure their code won't break just by flipping s flag. Why would you expect that a new revision can't cause existing code to compile? It means that "new" revisions can't fix old problems, and one thing you always get more of over time is perspective. If you don't want your code "broken", don't migrate to a new standard. That's the point of supporting old standards. Don't hobble new standards because you both want new things, but don't want old things to change.
- motorest 1y ago> Why would you expect that a new revision can't cause existing code to compile? For staters, because that would violate the goals and prioritites of the C++ as established by the C++ standardization committee. I could go on and on, but it's you who should provide any semblance of rationale: why do you believe existing software should break? What value do you see in it? Does it have any value at all?
- monkeyelite 1y agoAnd the cost of this is that every time I open a project in another language it’s broken and I have to make changes to fix all their little breaking changes.
- loeg 1y agoCompilers should add this as a non-standard extension, right? -ftrivial-auto-var-init=zero is a partial solution to a related problem, but it seems like they could just... not have UB here. It can't be that helpful for optimization.
- Matheus28 1y agoYes but it’s not portable. If zero initialization were the default and you had to opt-in with [[uninitialized]] for each declaration it’d be a lot safer. Unfortunately I don’t think that will happen any time soon.
- loeg 1y agoI don't really care if it isn't portable. I only have to work with Clang, personally. > If zero initialization were the default and you had to opt-in with [[uninitialized]] for each declaration it’d be a lot safer. I support that, too. Just seems harder than getting a flag into Clang or GCC.
- ryandrake 1y agoPortability is always for the other guy’s sake, not your own. That’s why so many people don’t care about it.
- loeg 1y agoAgain, I'm not opposed to the idea, it just seems more challenging logistically.
- motorest 1y ago> I don't really care if it isn't portable. You don't care because your job is not to ensure that a new release of C++ doesn't break production code. You gaze at your navel and pretend that's the universe everyone is bound to. But there are others using C++, and using it in production software. Some of them care, and your subjective opinions don't have an impact in everyone else's requirements. > I only have to work with Clang, personally. Read Clang's manual and check what compiler flags you need to flip to get that behavior. It's already there.
- deleted 1y ago[deleted]
- MichaelRo 1y ago>> Of all the warts, they all pale in comparison to the default initialization behavior. Come on. That's nothing compared to the horrors that lay in manual memory management. Like I've never worked with a C++ based application that doesn't have crashes lurking all around, so bad that even a core dump leaves you clueless as to what's happening. Couple OOP involving hundreds of classes and 50 levels deep calls with 100s of threads and you're hating your life when trying to find the cause for yet another crash.
- kaashif 1y ago50 levels deep? With some of the template metaprogramming I've seen, looking at just the types for just one level will not only fill your screen, but take up megabytes on disk...
- motorest 1y ago> Come on. That's nothing compared to the horrors that lay in manual memory management. Like I've never worked with a C++ based application that doesn't have crashes lurking all around, so bad that even a core dump leaves you clueless as to what's happening. Have you tried fixing the bugs in your code? That strategy has been followed by people writing code in every single language, and when used (even with C++) you do drive down the number of these crashes to a residual/purely theoretical frequency. Scenarios such as those you've described are rare. There should be more to them than the tool you're using to do your job. So why blame the tool?
- bluGill 1y agoI can write bad code in rust too. Rust makes it more difficult, but if you try hard you can abuse it to get the same hundreds of classes and 50 level deep calls, and 100s of threads. You can even do manual memory management in Rust - it isn't built into the language but you can call system APIs to allocate memory if you really want to be stupid. Don't do that is the answer. Good programmers have long ago written best practices guides based on hard learned experience. Newer languages (like Rust) were designed by people who read those guides and made a language that made using those features hard.
- josefx 1y ago> keep in mind that the old code was arguably already broken The code is only broken if the data is used before anything is written to it. A lot of uninitialized data is wrapped by APIs that prevent reading before something was written to it, for example the capacity of a standard vector, buffers for IO should only access bytes that where already stored in them. I have also worked with a significant number of APIs that expect a large array of POD types and then tell you how many entries they filled. > for a tiny performance improvement Given how Linux allocates memory pages only if they are touched and many containers intentionally grow faster then they are used? It reduces the amount of page faults and memory use significantly if only the used objects get touched at all.
- riehwvfbk 1y agoYou are very very unlikely to trigger Linux overcommit behavior by not initializing a member variable. It's even more unlikely for this to be a good thing. In effect, you are assuming that your uninitialized and initialized variables straddle a page boundary. This is obviously not going to be a common occurrence. In the common case you are allocating something on the heap. That heap chunk descriptor before your block has to be written, triggering a page fault. Besides: taking a page fault, entering the kernel, modifying the page table page (possibly merging some VMAs in the process) and exiting back to userspace is going to be A LOT slower than writing that variable. OK you say, but what if I have a giant array of these things that spans many pages. In that case your performance and memory usage are going to be highly unpredictable (after all, initializing a single thing in a page would materialize that whole page). OK, but vectors. They double in size, right? Well, the default allocator for vectors will actually zero-initialize the new elements. You could write a non-initializing allocator and use it for your vectors - and this is in line with "you have to say it explicitly to get dangerous behavior".
- motorest 1y ago> You are very very unlikely to trigger Linux overcommit behavior by not initializing a member variable. The problem with your assumption is that you're just arguing that it's ok for code to be needlessly buggy if you believe the odds this bug is triggered are low. OP points out a known failure mode and explains how a feature eliminates it. You intentionally ignore it for no reason. This assumption is baffling when, in the exact same thread, you see people whining about C++ for allowing memory-related bugs to exist.
- tails4e 1y agoEspecially when doing the right/safe thing by default is at worst a minor performance hit. They could change the default to be sane and provide a backwards compatible switch to pragma to revert to the less safe version. They could, but for some reason never seem to make such positive changes
- vrighter 1y agothat's the undefined keyword in zig. I love it. It makes UB opt-in and explicit
- fooker 1y ago> keep in mind that the old code was arguably already broken. Reminder than compiler devs are usually paid by trillion dollar companies that make billions with 'old code'.
- redandblack 1y agostupid question as I have not tpuched C++ since the 90s - can the IDEs not do this with all these now almost universal linters and AI assists. Maybe something that prompts before a commit and autoprompts before/after fixes to only the inititaization. Maybe simple as a choice in the refactoring menu? Rust - where are you for proposing this fix to C++ or, is it javascript?