- "Jonathan Blow: "C++ is a weird mess"" - 4 Updates
- How exceptions are implemented? - 8 Updates
- The best way to toggle the Touch Keyboard. - 6 Updates
- Some C++14 code - 2 Updates
- garbage collection - 4 Updates
- Some C++14 code - 1 Update
legalize+jeeves@mail.xmission.com (Richard): Jul 17 05:47PM [Please do not mail me a copy of your followup] Bart <bc@freeuk.com> spake the secret code >[...] To hear people on these groups tell >it, Windows is hopeless for software development. Because those of us who find ourselves productive in Windows have long since given up on the /. type bigots and their endless whinging. ...but back to the topic of the article. This is like the 40th time that someone has complained about C++ and introduced a new language to "solve" the problems that C++ has. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Terminals Wiki <http://terminals-wiki.org> The Computer Graphics Museum <http://computergraphicsmuseum.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
legalize+jeeves@mail.xmission.com (Richard): Jul 17 05:47PM [Please do not mail me a copy of your followup] Vir Campestris <vir.campestris@invalid.invalid> spake the secret code >IMHO Visual Studio is the best IDE out there. >These days I'm writing semi-embedded Linux stuff, and I miss Visual >Studio. I haven't found a Linux one as good. CLion comes close. Visual Studio Code is well respected as an editor on linux. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Terminals Wiki <http://terminals-wiki.org> The Computer Graphics Museum <http://computergraphicsmuseum.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
scott@slp53.sl.home (Scott Lurndal): Jul 17 06:16PM >[Please do not mail me a copy of your followup] [snip] > Visual Studio Code is well respected as an editor >on linux. Hm. Never even heard it referred to outside of this usenet forum. Well respected by who in the linux community? We have many linux programmers internally, and aside from a couple of interns who used eclipse, everyone else uses vim or emacs. |
woodbrian77@gmail.com: Jul 17 12:12PM -0700 On Tuesday, July 17, 2018 at 1:16:51 PM UTC-5, Scott Lurndal wrote: > Well respected by who in the linux community? > We have many linux programmers internally, and aside from a couple > of interns who used eclipse, everyone else uses vim or emacs. I use a mixture of vim and emacs to this day. Do Windows 10 programs still require a WSAStartup call? Getting rid of that is one thing Windows could do to be less annoying. They should have done it 10 years ago though. Brian Ebenezer Enterprises - Enjoying programming again. http://webEbenezer.net |
Thiago Adams <thiago.adams@gmail.com>: Jul 17 06:17AM -0700 What I am curious about, is how C++ implementations keep track of destructors that must be called for stack unwinding. For instance, if function F throws the destructor of X is called but the destructor of Y is not. int main() { X x; F(); Y y; } One way I can imagine is to have an state machine and annotate the state after constructor of X. and to call the destructors depending on what was the final state before exception. Other way that I guess is simple is to have something like a linked list of destructors and build this list after each constructor success. |
Bo Persson <bop@gmb.dk>: Jul 17 03:37PM +0200 On 2018-07-17 15:17, Thiago Adams wrote: > Other way that I guess is simple is to have something > like a linked list of destructors and build this list > after each constructor success. A popular way is table-driven exception handling, where a table describes what has to be done based on where you are in the executable when the exception is thrown. Here is one version: https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf Bo Persson |
Paavo Helde <myfirstname@osa.pri.ee>: Jul 17 04:49PM +0300 On 17.07.2018 16:17, Thiago Adams wrote: > Other way that I guess is simple is to have something > like a linked list of destructors and build this list > after each constructor success. Such approaches were indeed used in the past (i.e. in the last century). AFAIK, nowadays the compilers attempt to have zero overhead in the non-exceptional path. Only when an exception actually appears, the code will start to figure out in which point in the code it actually is and which destructors need to be run. The needed information is stored away in some tables elsewhere in the executable, in order to not interfere with the normal program execution. |
Thiago Adams <thiago.adams@gmail.com>: Jul 17 07:16AM -0700 On Tuesday, July 17, 2018 at 10:38:10 AM UTC-3, Bo Persson wrote: > Here is one version: > https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf I think where the documents says "landing pad" is something like I was imagining as states. Maybe landing state. But I cannot find where the state is changed. It must be something dynamic because the code generated for each function cannot see the internals of the called functions. (like F) I think when the stack is unwinding each function is visited and each function has it's own state in some place (maybe stack) that is used to understand what destructors must be called. I guess depending on the code we write we can have more states and bigger code (tables). Grouping all destructor maybe is better. for instance: int main() { X x; Y y; F(); } in this case if X and Y ctor don't throw then the only state is call ~X ~Y So using noexcept also could help generate less tables (states) |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 17 04:27PM +0200 On 17.07.2018 15:17, Thiago Adams wrote: > F(); > Y y; > } In this case, without a `catch` that catches the exception, you are not guaranteed that destructors are called. It's up to the implementation. > Other way that I guess is simple is to have something > like a linked list of destructors and build this list > after each constructor success. Yeah. :) Cheers!, - Alf |
Thiago Adams <thiago.adams@gmail.com>: Jul 17 07:29AM -0700 On Tuesday, July 17, 2018 at 11:16:20 AM UTC-3, Thiago Adams wrote: > the only state is call ~X ~Y > So using noexcept also could help generate less > tables (states) I put the code at compiler explorer site an I can see that there are two codes, one calls ~Y ~X and the other calls ~X I think they represent the "landing pads" ~Y ~X is the success code and ~X is when F1 throws. void F(int i) { X x; F1(i); Y y; } F(int): .LFB14: push rbp mov rbp, rsp push rbx sub rsp, 40 mov DWORD PTR [rbp-36], edi lea rax, [rbp-17] mov rdi, rax .LEHB0: call X::X() [complete object constructor] .LEHE0: mov eax, DWORD PTR [rbp-36] mov edi, eax .LEHB1: call F1(int) lea rax, [rbp-18] mov rdi, rax call Y::Y() [complete object constructor] .LEHE1: lea rax, [rbp-18] mov rdi, rax call Y::~Y() [complete object destructor] lea rax, [rbp-17] mov rdi, rax call X::~X() [complete object destructor] jmp .L12 .L11: mov rbx, rax lea rax, [rbp-17] mov rdi, rax call X::~X() [complete object destructor] mov rax, rbx mov rdi, rax .LEHB2: call _Unwind_Resume .LEHE2: .L12: add rsp, 40 pop rbx pop rbp ret .LFE14: .LLSDA14: .LLSDACSB14: .LLSDACSE14: |
Thiago Adams <thiago.adams@gmail.com>: Jul 17 07:32AM -0700 On Tuesday, July 17, 2018 at 11:27:12 AM UTC-3, Alf P. Steinbach wrote: > > } > In this case, without a `catch` that catches the exception, you are not > guaranteed that destructors are called. It's up to the implementation. My test code is: #include <stdio.h> struct X { X() { printf("X()\n"); } ~X() { printf("~X()\n"); } }; struct Y { Y() { printf("Y()\n"); } ~Y() { printf("~Y()\n"); } }; void F2(int i) { if (i > 0) { throw 1; } } void F1(int i) { F2(i); } void F(int i) { X x; F1(i); Y y; } int main() { try { F(3); } catch(...) { } return 0; } |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 17 06:21PM +0200 On 17.07.2018 16:32, Thiago Adams wrote: > } > return 0; > } Yes, that `catch` does make a difference. Note that the `return 0;` is superfluous. It's the default for `main`, in both C and C++. Cheers!, - Alf |
Jeff-Relf.Me @.: Jul 17 01:14AM -0700 |
boltar@cylonHQ.com: Jul 17 09:03AM On Mon, 16 Jul 2018 19:31:37 +0300 >> and Windows 10 is no different. >There are lots of computers where there is no C:\Program Files, but for >example C:\Programme or C:\Archivos de programa. Thats just fuckwittery on the part of Microsoft. You wouldn't go into a unix install in france or spain and expect to see /maison or /casa instead of /home. Major OS paths should be standardised no matter what the locale. |
SilverSlimer <silver@slim.er>: Jul 17 11:50AM On Tue, 17 Jul 2018 09:03:42 +0000, boltar wrote: > unix install in france or spain and expect to see /maison or /casa > instead of /home. Major OS paths should be standardised no matter what > the locale. Completely agreed. It should be possible for a user who installed a system in English to switch it over to something like Spanish and have all of the software translate as well without any negative consequences. I'm not sure whether Linux allows it to consistently change on demand (I doubt it) but Windows should have made it possible considering they charge for the operating system. |
Paavo Helde <myfirstname@osa.pri.ee>: Jul 17 03:36PM +0300 > Thats just fuckwittery on the part of Microsoft. You wouldn't go into a > unix install in france or spain and expect to see /maison or /casa instead of > /home. Major OS paths should be standardised no matter what the locale. Agreed, but unfortunately this does not change the reality. |
Paavo Helde <myfirstname@osa.pri.ee>: Jul 17 03:41PM +0300 On 17.07.2018 14:50, SilverSlimer wrote: > I'm not sure whether Linux allows it to consistently change on demand (I > doubt it) but Windows should have made it possible considering they > charge for the operating system. Yes, that's exactly the idea. All programs are supposed to call the SHGetKnownFolderPath() Windows SDK function to find out the current name of such folders, so that they could continue to work after such switch. |
Snit <usenet@gallopinginsanity.com>: Jul 17 08:41AM -0700 On 7/17/18 4:50 AM, SilverSlimer wrote: > I'm not sure whether Linux allows it to consistently change on demand (I > doubt it) but Windows should have made it possible considering they > charge for the operating system. If you move an app it should keep working. -- Personal attacks from those who troll show their own insecurity. They cannot use reason to show the message to be wrong so they try to feel somehow superior by attacking the messenger. They cling to their attacks and ignore the message time and time again. <https://youtu.be/H4NW-Cqh308> |
Juha Nieminen <nospam@thanks.invalid>: Jul 17 12:14PM > pass over all of them anyway to test for collisions and update the > position, and inside this loop you can manage and update the active > flag. Compacting the buffer can also be combined with this loop. So, essentially, you want to implement your own memory management to handle the projectiles, instead of using the one provided by the system. Using memory compaction at the same time you are traversing the data container (ie. removing gaps by moving elements to the first unused slot in the container as you traverse it) may avoid having to traverse a list with huge gaps, but are you really going to see a signficant performance benefit from this scheme? You are only adding more complication to your own code. (Also, if it so happens that there's a significant amount of data stored for each projectile, assigning them around in your data container may be a relatively heavy operation and might offset any performance benefit you gain from not having to call 'new' and 'delete' so often. Depending on the situation, of course.) In the end, this projectile management routine might not be any sort of bottleneck anyway, so it comes a bit to premature optimization. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 17 04:16PM +0200 On 16.07.2018 18:33, Bart wrote: > if (!(c == cr || c == lf || c == tab || c == space)) ... > which also has short-circuit evaluation as well as being less likely to > have people scratching their heads. With the headers that I posted, the above would be expressed as -------------------------------------------------------------------------- #include <cppx/stdlib-wrappers/Set_.hpp> // https://github.com/alf-p-steinbach/cppx #include <stdlib/c/stdio.hpp> // https://github.com/alf-p-steinbach/Wrapped-stdlib #include <stdlib/extension/type_builders.hpp> #include <stdlib/string.hpp> // std::stoi using namespace std; using namespace stdlib::ext::type_builders; // raw_array_, ptr_ auto main( const int n_args, raw_array_<ptr_<char>> args ) -> int { using cppx::Set_; const char ch = char( stoi( n_args == 2? args[1] : "Gah!" ) ); if( in( Set_{ '\r', '\n', '\t', ' ' }, ch ) ) { printf( "It's a whitespace character!\n" ); } } -------------------------------------------------------------------------- But the simple notation Set_{ '\r', '\n', '\t', ' ' } is a design bug, because when there is a Set_ constructor accepting a `std::initializer_list` like that, the C++ constructor overload resolution logic will default to interpret any "{ ... }" argument list with two or more arguments, as an initializer_list: -------------------------------------------------------------------------- #include <iostream> #include <initializer_list> using namespace std; void say( const char s[] ) { cout << s << '\n'; } struct S { S( int ) { say( "One int arg" ); } S( int, int ) { say( "Two int args" ); } S( int, double ) { say( "int and double args" ); } S( initializer_list<int> ) { say( "initializer_list" ); } }; auto main() -> int { (void) S{1}, S{1, 2}, S{1, 2, 3}; // S{ 4, 2.71828 }; <-- Doesn't even compile! :( (void) S( 4, 2.71828 ); } -------------------------------------------------------------------------- Output: initializer_list initializer_list initializer_list int and double args I actually ran into that problem for class `Set_` without understanding what it was, when I coded this up. I should have noticed the big red flag, I've discussed this many times and advised others about it. E.g. `std::vector` and `std::string` have this problem because these standard library classes were designed before `std::initializer_list` (a curly brace enclosed list of values) was introduced in C++11... So instead of the simple notation, the direct constructor invocation should really be like Set_{ tag::Values{}, {'\r', '\n', '\t', ' ' } } and since that's so ugly there should be factory function, used like values( {'\r', '\n', '\t', ' ' } ) But then, it's just plain inefficient to convert a list of four `char` values to a `std::unordered_set<char>`... So instead the `in` function for raw arrays provided in the original header should be used, like in( {'\r', '\n', '\t', ' '}, ch ) But that doesn't compile because, second bug, I forgot a `const` in this code: template< class Key, Size n, class Arg > auto in( ref_<raw_array_of_<n, Key>> a, ref_<const Arg> v ) -> bool { return in_range( begin( a ), end( a ), v ); } Or actually I didn't "forget" the `const`. I mistakenly thought that `Key` would be deduced as `const char` for the example above, and so on. And I have no idea why it isn't deduced! Anyway I've now fixed those two bugs, checked that the earlier example still works nicely, and updated on GitHub, so the last `in` example above now works. You can't get it simpler than that, I think. Or more efficient. :) Cheers!, - Alf |
Soviet_Mario <SovietMario@CCCP.MIR>: Jul 17 03:38AM +0200 Il 15/07/2018 18:34, Paavo Helde ha scritto: > In C++ the only sensible way to have GC is to logically > think that all allocated objects are leaked, but that's ok > as you have got infinite memory. Uh ... what do you actually mean with this "you have infinite memory" ? To use it up freely, never caring, and to simply rely on try/catch/finally in case some error occurs ? > Behind the scenes the > memory gets reused of course, again I can't understand. Do you mean at the OS' memory management level ? Or by some "hidden" code generated by modern compilers ? Or even sth else ... > released properly and are not left to GC which will run in > unpredictable times in a random thread. > I believe the current consensus is that with RAII one can at the very outdated time I firstly read of RAII, memory allocation was one of such resources. Why this distinction now ? > control both memory and non-memory resources in the same way > and with less hassle, so RAII all the way down it is. Thus > GC is effectively not needed in C++. SNIP ah, another question ... when you speak of POOLS, you mean allocating on the heap (or even statically) a big contiguous chunk and then overload new/delete into more specialized (and faster) forms which pick up some space within that chunk ? Ciao -- 1) Resistere, resistere, resistere. 2) Se tutti pagano le tasse, le tasse le pagano tutti Soviet_Mario - (aka Gatto_Vizzato) |
Rosario19 <Ros@invalid.invalid>: Jul 17 11:09AM +0200 On Mon, 16 Jul 2018 21:20:24 +0100, Vir Campestris wrote: >and every so often it plain crashes and burns. To me it's obviously got >some kind of resource leak. >Andy the leak can be in C++ even if there are no leak, if the allocator (malloc()/free() or new()/delete()) not has one algo for return to OS the memory (zeroed first) that can |
Rosario19 <Ros@invalid.invalid>: Jul 17 11:10AM +0200 On Tue, 17 Jul 2018 11:09:21 +0200, Rosario19 wrote: >the leak can be in C++ even if there are no leak, >if the allocator (malloc()/free() or new()/delete()) not has one algo >for return to OS the memory (zeroed first) that can the leak can be in C++ even if there are no leak, if the allocator (malloc()/free() or new()/delete()) not has one algo for free to OS the memory (zeroed first) that can |
Paavo Helde <myfirstname@osa.pri.ee>: Jul 17 04:04PM +0300 On 17.07.2018 4:38, Soviet_Mario wrote: > Uh ... what do you actually mean with this "you have infinite memory" ? > To use it up freely, never caring, and to simply rely on > try/catch/finally in case some error occurs ? GC basically means leaking all memory, to be cleaned up sometimes later. This has nothing to do with errors. > Do you mean at the OS' memory management level ? > Or by some "hidden" code generated by modern compilers ? > Or even sth else ... By the garbage collector of course. The recent C++ standards include optional support for the garbage collector, I guess this would count as "hidden code added by the compiler". But I am not sure if any compiler has actually implemented this. Alternatively, you add non-hidden code like Boehm collector into your program. If there is a plenty of memory, the GC might indeed decide there is no need to free any memory at all and it can leave the memory cleanup to OS at the process exit. But this is a corner case. >> I believe the current consensus is that with RAII one can > at the very outdated time I firstly read of RAII, memory allocation was > one of such resources. Why this distinction now ? Memory can be released in any thread in any time without a direct impact to the running program. That makes GC possible. Other resources must be released more deterministically. A file must be flushed and closed before it can be processed. A mutex lock must be released in the same thread. A database transaction must be committed before the program exit, or it would be lost. Etc. > the heap (or even statically) a big contiguous chunk and then overload > new/delete into more specialized (and faster) forms which pick up some > space within that chunk ? Yes, few big chunks on the heap. |
ram@zedat.fu-berlin.de (Stefan Ram): Jul 17 11:22AM >It's a mystery how you get from the above to the following: >This is why expressiveness in the code is important - within reason [Some C++14 content at the end of this post] The part that you possibly do not understand ironically is using what usually is praised for its expressiveness, i.e., the stream part: >>java.util.stream.IntStream.rangeClosed( 32, 126 ). >>filter( pred::apply ). >>forEach( c -> java.lang.System.out.print(( char )c )); . This produces a sequence of the numbers from 32 to 126 (1st line) and then only keeps those numbers for which the predicate »pref« yields »true« (2nd line), eventually each of those remaining numbers is being printed (3rd line). Note some lines ending in a period ».«. It's equivalent to: for( int c = 32; c <= 126; ++c ) if( pred.apply( c )) java.lang.System.out.print(( char )c )l , where »c« is a hitherto unused variablename. For an example showing the expressiveness, we can obtain a Lotto (Lottery) tip (6 out of 49) from: Main.java public class Main { public static void main( final java.lang.String[] args ) { final int total_size = 49; final int selection_size = 6; final java.util.List<java.lang.Integer> numbers = java.util.stream.IntStream.rangeClosed( 1, total_size ).boxed(). collect( java.util.stream.Collectors.toList() ); java.util.Collections.shuffle( numbers ); java.lang.System.out.println ( java.util.Arrays.toString ( numbers.subList( 0, 6 ).toArray() )); }} Protokoll [31, 11, 15, 40, 47, 44] While Java and C++ have developed into different directions, one also can see that this "variablefree"/"loopfree" style of programming also can be written in C++, albeit using different means. main.cpp #include <algorithm> // ::std::random_shuffle, ::std::copy_n #include <array> #include <iostream> #include <iterator> // ::std::ostream_iterator #include <numeric> // ::std::iota #include <ostream> #include <random> int main() { using num = int; using size_type = ::std::vector< num >::size_type; auto output { ::std::ostream_iterator< int >( ::std::cout, " " )}; constexpr size_type total_size = 49; constexpr size_type selection_size = 6; ::std::mt19937 algorithm{ ::std::random_device{}() }; ::std::array< num, total_size >numbers; { constexpr num offset = 1; ::std::iota( begin( numbers ), end( numbers ), offset ); } shuffle( begin( numbers ), end( numbers ), algorithm ); copy_n( begin( numbers ), selection_size, output ); ::std::cout << '\n'; } Protokoll 45 19 34 2 26 24 A problem with the implementation used (based on MinGW) is that ::std::random_device{}() does not really deliver any entropy, and so the program always yields the same output. One can line up Java parts with corresponding C++ parts: Generate <total_size> numbers: Java: final java.util.List<java.lang.Integer> numbers = java.util.stream.IntStream.rangeClosed( 1, total_size ).boxed(). collect( java.util.stream.Collectors.toList() ); C++: ::std::array< num, total_size >numbers; { constexpr num offset = 1; ::std::iota( begin( numbers ), end( numbers ), offset ); } Shuffle: Java: java.util.Collections.shuffle( numbers ); C++: shuffle( begin( numbers ), end( numbers ), algorithm ); Print the first <selection_size>: java.lang.System.out.println ( java.util.Arrays.toString ( numbers.subList( 0, selection_size ).toArray() )); copy_n( begin( numbers ), selection_size, output ); ::std::cout << '\n'; |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment