Re:C++ and zombies: a moving question
by Animats on Friday October 31, 2014 @02:33PM
(#8540311)
Oh, the destructive move problem. I thought this was about "re-animation", the horror introduced with Microsoft Managed C++, where, if a GC-called destructor saves a pointer to the object being destroyed, the object has to be "re-animated".
No, this is just the destructive move problem for single ownership pointers.
It's an use case for "swap" as a language primitive.
The real problem is that you just can't make single-ownership pointers work right in C++ via the template mechanism. I tried a few times, over a decade ago. (http://animats.com/papers/languages/index.html) It takes a more global look than you have down inside a template. You need language-level support.
Rust does this. It's not inherently hard. It's just extremely hard to retrofit to the C++ model. Look at the history of auto_ptr, and now unique_ptr in C++. The pain. The anguish. The decades of headaches. The unnecessary complexity. The pain.
Re:C++ and zombies: a moving question
by CJefferson on Friday October 31, 2014 @03:08PM
(#8540524)
The biggest problem with destructive move in C++ (and one I personally think is unfixable, but I'm happy to be proved wrong), is that in most cases algorithms must be sure to recreate any variable they are not responsible for, as it will be destroyed later. There isn't any way of checking if some memory has already been destroyed, and adding any kind of flag just gets us back to the same position really. In particular I tried writing an exception safe std::sort (so make sure when std::sort exits all variables are reconsructed again), and it is an extremely difficult undertaking.
In general I find the lack of destructive move isn't a serious problem -- designing variables so their 'default state' is very cheap to construct isn't usually a major cost.
Re:C++ and zombies: a moving question
by thebear on Friday October 31, 2014 @03:37PM
(#8540684)
I think it was Dave Abrahams who first brought up the issue of destructors with side effects and their implications for move semantics. For example, a destructor may have the side effect of releasing a lock. If I remember correctly, Dave's advice was to write your move operations in such a way that they always perform at least those destructor actions that have side effects. I seem to remember that he discussed this on his cpp-next blog, but the site appears to be down. Does anybody know if those blog posts are available somewhere?
Re:C++ and zombies: a moving question
by meetingcpp on Friday October 31, 2014 @04:01PM
(#8540811)
Well, of course accessing the value of fh after foo would be fatal.
But how would you then sort a container of moveable-only objects?
An object should be accessible for reassigning a value after its move, as its often needed for algorithms, thats exactly why the C++ Standard mandates this. Move does really only make sense if the class holds a moveable allocation, such as a container, array etc., which makes copying expensive.
Re:C++ and zombies: a moving question
by dbaupp on Friday October 31, 2014 @08:39PM
(#8541798)
> An object should be accessible for reassigning a value after its move, as its often needed for algorithms, thats exactly why the C++ Standard mandates this.
The same is true in Rust. A moved-from value can be reassigned, but cannot be used (compile enforced) until it is reassigned. :)
Re:C++ and zombies: a moving question
by cheez on Friday October 31, 2014 @03:45PM
(#8540718)
How often do people make this error? I know, it's a terrible error but I code every day (maybe my opinion is not relevant for this reason) and I rarely come across this issue.
Re:C++ and zombies: a moving question
by pjmlp on Sunday November 02, 2014 @02:44AM
(#8545976)
Big projects are often composed anywhere from 10 developers up to 100 or more.
Usually with high rotation of developers coming and going, since parts of the project tend to be delegated to be other companies, many times with developers that aren't all at the same skill level.
When you work at this scale, memory errors and misuse of resource are quite common.
No developer is able to have the whole code on his/her head and sometimes also does not have the time to understand the whole codebase.
So mistakes happen quite often.
This is why C got out of love in the enterprise or why companies like Google and JPL have such strict C++ design guide.
Re:C++ and zombies: a moving question
by general_failure on Friday October 31, 2014 @05:00PM
(#8541108)
I feel like a complete idiot when I read these articles :-( I can hardly even understand the issues because c++ have gotten to a point where I have to strain myself very hard to even understand the problem (forget the solution). And I have been programming with c++ for many years (but c++11 ignorant).
No, this is just the destructive move problem for single ownership pointers. It's an use case for "swap" as a language primitive.
The real problem is that you just can't make single-ownership pointers work right in C++ via the template mechanism. I tried a few times, over a decade ago. (http://animats.com/papers/languages/index.html) It takes a more global look than you have down inside a template. You need language-level support.
Rust does this. It's not inherently hard. It's just extremely hard to retrofit to the C++ model. Look at the history of auto_ptr, and now unique_ptr in C++. The pain. The anguish. The decades of headaches. The unnecessary complexity. The pain.
But I am also spoiled by Niklaus Wirth legacy in language design and safe systems programming. As well as ML languages.
C++14 feels quite modern, and I enjoy playing with it on hobby projects where I have full control, but I don't miss those C++98 enterprise code bases.
In general I find the lack of destructive move isn't a serious problem -- designing variables so their 'default state' is very cheap to construct isn't usually a major cost.
File fh = File(fopen("file.txt"));
foo(std::move(fh));
Using fh after foo() would yield a compile error in Rust. It does not in C++.
An object should be accessible for reassigning a value after its move, as its often needed for algorithms, thats exactly why the C++ Standard mandates this. Move does really only make sense if the class holds a moveable allocation, such as a container, array etc., which makes copying expensive.
The same is true in Rust. A moved-from value can be reassigned, but cannot be used (compile enforced) until it is reassigned. :)
Usually with high rotation of developers coming and going, since parts of the project tend to be delegated to be other companies, many times with developers that aren't all at the same skill level.
When you work at this scale, memory errors and misuse of resource are quite common.
No developer is able to have the whole code on his/her head and sometimes also does not have the time to understand the whole codebase.
So mistakes happen quite often.
This is why C got out of love in the enterprise or why companies like Google and JPL have such strict C++ design guide.
To Quote Eric Niebler: "I want you to fear r-value references, like one could fear god" (last year at Meeting C++)
[1]except things like forwarding in templates, but thats fairly easy.