6 ms·
>I program in C++ as a hobby and typescript for my day job. I would say if anything it's just as hard trying to figure out why a JS object is undefined as it is
by deltaonefour 4y ago
>I program in C++ as a hobby and typescript for my day job. I would say if anything it's just as hard trying to figure out why a JS object is undefined as it is finding out why you get a segfault in C++.
I programmed both for my career. At one point I was literally full stack as in device and sensor integration code all the way through application code and databases to react and typescript on the browser.
An undefined can be traced backwards following previous logic. You can also set breakpoints earlier and earlier and eventually find the problem. It's tedious but straightforward. Additionally the error is reproducible.
In C++ If you write to memory out of bounds anything can happen and the behavior is actually random. Changing things in unrelated places can actually affect the outcome and give you false positives.
It might hit an unallocated page, in which case you get a segfault. Or it might hit unused data on a page that is allocated to your process in which case it won't have any practical effect (unless it is properly initialized afterwards, overwriting your first, illegal, write, and you then try to read from it, expecting the original (invalid) value to still be there. Or it might hit data that's actually in use, in which case you'll get errors later, when the program tries to read that data.
Pretty much the same scenarios exist when reading data. You can be lucky and get a segfault immediately, or you can hit unused and uninitialized memory, and read garbage data out (which will most likely cause an error later, when that data is used), or you can read from memory addresses that are already in use (which will also give you garbage out).
There is no direct backwards path from a segfault to the source of the error. All you know is that a segfault happened here, and the cause of the segfault must've happened somewhere before it.
Sure you can also code safely in a way that avoids these foot gun errors. But you can do the same in any language. People have been doing this with the "Good parts" of javascript prior to ES6 and typescript for years, but that's not the point.
There are also tools like valgrind and asan, but these tools are ALSO not the point.
What we're talking about is the difference in safety intrinsic to the language not intrinsic to your style of coding. C++ is definitively worse. OpenGL is also a lower level C library and tracing errors is also hard for the same reason why C++ has segfaults. Basically there's no intrinsic checks anywhere so although things are faster, things are much more error prone as a result.
If you really want to have fun try vulkan.
- _gabe_ 4y agoI completely agree with all your points except for the fact that tracing a segfault is harder than tracing an undefined object in JS. JavaScript will happily chug along with an undefined object and do random stuff as well. It may not throw any errors or warnings, and you'll only realize something is wrong because your app is behaving weirdly. This is the same problem as a C++ segfault. And coding styles absolutely have a role to play in how safe a language is. A good developer can work just as efficiently in C or C++ as they can in something like Rust. Especially if they've built tooling to catch nasty bugs like heap corruption or memory leaks (which takes a couple hours at most). This doesn't mean I'm advocating everyone abandon safe languages :) I haven't had a chance to try out a language like Rust, but I definitely want to give it a try at some point. Safe languages are trying to solve specific self induced headaches which is awesome. A couple other languages I'm very interested in are Odin and Jai. Anyways, language safety is a great goal, but that doesn't mean a good developer can't avoid a lot of memory related footguns with a bit of forethought and planning (and again, yes, I know a safer language avoids those footguns by default :)
- deltaonefour 4y ago>JavaScript will happily chug along with an undefined object and do random stuff as well. Javascripts behavior is not random. The exception thrown by an undefined object is deterministic meaning you run the program again with the SAME input parameters the program will crash at the same point. The only time it could be random is if you have time as input or a random number generator that effects the logic. Additionally the undefined can be traced backwards logically by following the datapath to the source. You can do this by reading code or setting break points in the code and looking at the state along each step. Both of the above DO not happen in an out of bounds memory error. A segfault may not even occur. Your program can run and nothing can happen. Then suddenly your program can run and then segfault at a random location. The segfault happens randomly and at random locations and there is no direct datapath that leads to the source. >And coding styles absolutely have a role to play in how safe a language is. A good developer can work just as efficiently in C or C++ as they can in something like Rust. Especially if they've built tooling to catch nasty bugs like heap corruption or memory leaks (which takes a couple hours at most). I don't think you have much experience with C++ if you're unaware how much harder debugging a segfault is than an undefined. Modern C++ doesn't need additional tooling and you can definitely stay within the bounds of features introduced in C++11 and above for safety, this is trivial and easily done. However segfaults can still creep in via libraries or other entry ways. This occurs especially for extremely large code bases. >but that doesn't mean a good developer can't avoid a lot of memory related footguns with a bit of forethought and planning Have you worked on large codebases with hundreds of developers? Even when every developer attempts to follow good practices or always uses smart pointers, eventually just via statistics some C++ foot gun accidentally goes off. You are infinitely better off in a language where the foot gun doesn't even exist. Additionally some apis and writing really optimized code requires use of foot guns. Many safety features like smart pointers just have too high of a performance overhead so we avoid and use archaic stuff like 'new'. CUDA for example doesn't allow you to use the std and introduces new foot guns such as dereferencing a device pointer on a host device. You can get around this by wrapping device pointers in a special device type but again this is overhead and the safety abstractions are not zero cost. Safety has a performance cost and making this performance cost as small as possible is why C++ is the way it is.