Live data from Hacker News

Mysterious Moving Pointers

blomqu.ist

51–60 of 68 posts

Re: Mysterious Moving Pointers

#51
post #22
post #7

Earlier quoted context omitted.

That’s a bit like saying you know C++ but not streams or templates, or C but not floating point operations. It’s probably worth learning STL. Anyway, the reason to use move instead of copy is for performance. Move constructors are faster because they can leave the source object modified (e.g., take over control of a pointer to deep contents). This falls apart when the move constructor can throw, because the container…

I phrased that badly - it should have been “I don’t know every edge case in the STL, and so I don’t know why this would have different behavior”. However thanks for explaining the issue. This one is obvious and I just completely failed to think about how you ensure the source object is in a safe state if an exception occurs part way through moving the source data. It seems to imply the old MSVC behaviour was incorrec…

Fair enough. Honestly, there are very few people in the world who could confidently claim that they know all of the STL. The first place I worked at disallowed it (MSVC 5 was fresh then, so it was somewhat understandable), and we had our own performance centric data structures. But the value of container classes and promises about performance first really hit me when I went to my next job and dug in on the STL. Truly eye opening stuff, and absolutely available for reading (which was pretty cool at the time).

Re: Mysterious Moving Pointers

#52

Earlier quoted context omitted.

> I remember the C++ ca. 1994 year when I started my career. It was C with Objects back then It is possible, and perhaps even likely that the C++ you wrote in 1994 was indeed this "better C" and maybe even the C++ you read, the language Stroustrup wrote about in 1985 although "C with Objects" is much older still. The ISO document (C++ 98 aka ISO 14882:1998) was four years into your future in 1994, but the committee t…

I believe that not many developers really wanted C++ and craved Object Pascal instead. I don't like Pascal but I have to admit that Object Pascal is a succint and successful addition of OO to a manually memalloc language, whereas C++ is neither.

As someone that went from Turbo Pascal to C++, while enjoying Borland's ecosystem, the reasoning was clear.

A programming language that at a time offered similar security and features, with much better portability.

Never was a big C fan, with Object Pascal and C++ on my toolbox.

Re: Mysterious Moving Pointers

#53

Earlier quoted context omitted.

I remember the C++ ca. 1994 year when I started my career. It was C with Objects back then. And it was great! C++ was better C, it was easy for any C dev to convince him/her to jump to it. I recently had to work with C++ code and... it is not a happy story anymore: - Lots of magic like described here - F**ing templates - for those who like them, did you ever see a C++ core file? Or tried to understand a single symbol…

> I remember the C++ ca. 1994 year when I started my career. It was C with Objects back then It is possible, and perhaps even likely that the C++ you wrote in 1994 was indeed this "better C" and maybe even the C++ you read, the language Stroustrup wrote about in 1985 although "C with Objects" is much older still. The ISO document (C++ 98 aka ISO 14882:1998) was four years into your future in 1994, but the committee t…

Turbo C++ for Windows 3.1, released in 1993, already had support for templates in its initial design form.

Borland C++ 2.0, or 3.0, rewrote BIDS from preprocessor magic into templates.

CSet++ for OS/2, also early 1990s also offered template based collections.

By 1996, MFC introduced template based collection classes as well.

Re: Mysterious Moving Pointers

#54

There is a lesser known cousin to std::vector that doesn't have to move nor copy its elements when adding new elements, and that is std::deque.

Right. But of course std::deque comes with a cost; iteration is slower and memory footprint is bigger.

Re: Mysterious Moving Pointers

#55

Earlier quoted context omitted.

I remember the C++ ca. 1994 year when I started my career. It was C with Objects back then. And it was great! C++ was better C, it was easy for any C dev to convince him/her to jump to it. I recently had to work with C++ code and... it is not a happy story anymore: - Lots of magic like described here - F**ing templates - for those who like them, did you ever see a C++ core file? Or tried to understand a single symbol…

> - F*ing templates - for those who like them, did you ever see a C++ core file? Or tried to understand a single symbol? I have 20+ years of experience writing C++. Yes, I've looked at "core" C++ headers and source. The most annoying part to me is style (mixed tabs and spaces, curly braces at wrong places, parenthesis or not, the usual style complaints). But other than that they're very readable to a seasoned C++ eng…

>> - Fing templates - for those who like them, did you ever see a C++ core file? Or tried to understand a single symbol?*

> I have 20+ years of experience writing C++.

> Yes, I've looked at "core" C++ headers and source.

https://en.wikipedia.org/wiki/Core_dump

Re: Mysterious Moving Pointers

#56
I must be misunderstanding something from this article. With:

struct Node {

    std::vector connections;
};

struct Connection {

    Node* from, to;
};

Does this mean that to create the vector of connections, Nodes are created, and references are taken to store in the Connections? And then the Nodes are stored in the list, with std::move()?

I don't understand why you would want to go down that road. Intuitively, I would assume that you are not safe from an object copy somewhere down the line and your graph then comes crashing down like a house of cards. Wouldn't it make more sense to store the nodes as pointers? If you like to live dangerously, something like:

struct Graph {

    std::vector> nodes;
};

Or better:

struct Graph {

    std::vector>> nodes;
};

The later will give you plenty of warnings if you do not copy Nodes around with std::move().

Or less performant, but maybe safer, std::shared_ptr, together with:

struct Connection {

    std::weak_ptr from, to;
};

so that you have some check guarantees before access?

Re: Mysterious Moving Pointers

#58
post #5

This is a great reminder of the pox that was Microsoft of the early part of the millennium. Besides an allergy to investing in web standards, they were woefully behind in their language support. Their non-adoption of modern C++ standards held client security back for a decade, and arguable held language standards development back.

Having only worked with gcc and clang, OP’s code looked completely fine to me and I was baffled why many comments think the code is at fault. Judging by this page [1], I agree this is entirely MSVC’s doing. [1] http://howardhinnant.github.io/container_summary.html

Yeah, Microsoft absolutely should've made their containers use throwing move-constructors in violation of the standard, in order to better adhere to the standard.

In reality, it's a defect in the standard, plus a quality-of-implementation issue in the Microsoft's C++ Standard Library.

Re: Mysterious Moving Pointers

#59
post #2

I know C++ the language but not the STL (the overwhelming abundance of UB and total lack of safety make it an anathema), so my question is why the STL allows/requires non-move here copying here dependent on whether an object has a no throw move constructor? Note I’m not asking about move constructor vs memmove/cpy but rather the use of copy constructor vs move depending on exception behavior? Is it something like pre…

UB is a feature; people who keep on fighting it are such a pain. Regarding your question, nothrow operations are essential to maintaining invariants. And maintaining invariants is how you make code correct in a world where UB exists.

Yes, if the programmer maintains certain invariants, the C's flavour of UB allows the compiler to take advantage of those invariants for performance gains, by omitting run-time checking for those invariants.

The problem with this flavour of UB being a programmer's promise "this is fine, trust me, no run-time checks needed" to the compiler is that a) it's made by the programmer by omitting said run-time checks ― and that often happens accidentally, not intentionally; b) the compilers are really bad at pointing out to the programmer places where they took advantage of such promises, which really complicates the task of writing conforming programs. Every time I add two int's, I promise to the compiler that an overflow won't happen: and of course, the moment an UB happens, all invariants cease to hold, so trying to find the initial bug where you've accidentally broke one of invariants turns into a nightmare.

Re: Mysterious Moving Pointers

#60

I must be misunderstanding something from this article. With: struct Node { std::vector connections; }; struct Connection { Node* from, to; }; Does this mean that to create the vector of connections, Nodes are created, and references are taken to store in the Connections? And then the Nodes are stored in the list, with std::move()? I don't understand why you would want to go down that road. Intuitively, I would assum…

I don't think you're misunderstanding, it's a strange choice to make even if the example here loses context to make it easier to make the point. It wasn't code that anyone currently here wrote and because it worked with the old compiler, nobody really touched it. I believe the nodes are pushed into the list before adding connections but I don't think that changes the point you're trying to make. That said, one's intuition is different from another's and I don't think it's unfair to assume that pushing into a vector of lists won't cause every existing list to be copied. For that to be the actual behavior is kind of disgusting. It may make more sense to create pointers here but that's a larger change to deal with and ensure correctness versus just swapping the vector out for another list. I don't claim to like that solution but it seems to me like legacy C++ code in general is fragile enough as it is, the less I have to change to fix bugs the better.
Post reply on HN