Monday, July 16, 2018

Digest for comp.lang.c++@googlegroups.com - 23 updates in 4 topics

Vir Campestris <vir.campestris@invalid.invalid>: Jul 16 09:20PM +0100

On 16/07/2018 13:52, Andrew Goh wrote:
> thanks for all the responses, actually coming from the java world c++ is quite as 'native' to me, i'd guess most 'java programmers' (and so do other similar managed languages) are somewhat spoilt by garbage collection.
 
I have a satnav that runs Android, so the app will be Java.
 
Every few weeks I have to reboot it. It usually goes deaf (ignores voice
control); sometimes it doesn't switch between day and night correctly;
and every so often it plain crashes and burns. To me it's obviously got
some kind of resource leak.
 
Andy
Vir Campestris <vir.campestris@invalid.invalid>: Jul 16 09:46PM +0100

On 16/07/2018 06:45, bitrex wrote:
> few good use cases in modern C++, modern C++ which uses it all over the
> place is simply not well-designed code. I think I've used it in
> something like three or four times. ever.
 
I came into a project that was using raw pointers for objects with a
complex lifecycle. I halved the crash rate by swapping them for
shared_ptr and weak_ptr as appropriate. There were a mixture of leaks
and use-after-free problems.
 
They are overused; there are places where a unique_ptr will do the job.
But IMHO if you see thing* in modern C++ that's what the XP guys call a
code smell. It's dangerous.
 
Andy
woodbrian77@gmail.com: Jul 16 02:49PM -0700

On Monday, July 16, 2018 at 3:46:09 PM UTC-5, Vir Campestris wrote:
 
> They are overused; there are places where a unique_ptr will do the job.
> But IMHO if you see thing* in modern C++ that's what the XP guys call a
> code smell. It's dangerous.
 
If it's a data member, it may be fine:
 
https://stackoverflow.com/questions/38780596/how-to-handle-constructors-that-must-acquire-multiple-resources-in-an-exception#38780597
 
 
Brian
Ebenezer Enterprises
https://github.com/Ebenezer-group/onwards
bitrex <user@example.net>: Jul 16 07:04PM -0400

On 07/16/2018 04:46 PM, Vir Campestris wrote:
> But IMHO if you see thing* in modern C++ that's what the XP guys call a
> code smell. It's dangerous.
 
> Andy
 
I use raw pointers sometimes simply because I often use C++ to code for
devices with very small amounts of memory, like 4k sometimes. Smart
pointers are right out. But on devices like that I also never use "new"
except at startup so it works out.
 
C++1x provides many nice features over C that are welcome on platforms
like that regardless. It doesn't hurt performance or stupendously bloat
the code or all those old wives tales.
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Jul 16 04:09PM -0700

On 7/16/2018 12:18 AM, Siri Cruise wrote:
 
> reference count:
> Cannot cope with cyclic references naively.
> Garbage is identified immediately on becoming garbage.
 
Fwiw, proxy reference counting can handle cyclic links in
data-structures it protects. One point, to remove and delete an item,
one only needs to make it non-reachable to other threads, then defer the
deallocation until after quiescent period has elapsed. Making it
unreachable can be as simple as removing it from a linked list, or
whatever data-structure one uses. Reader threads can be iterating
through cyclic linked data-structures while writer threads concurrently
add and remove elements to/from them.
 
 
Bart <bc@freeuk.com>: Jul 16 03:27PM +0100

On 16/07/2018 13:45, Paavo Helde wrote:
> }
 
> bool In(char c, const set& x) {
>   return x[c-kMin];
 
In general this needs a range check, as you want indices outside the
span of the set to return 0. Here you've arranged the index to be an
char type with the same limits as the set.
 
The problem is that someone might pass 1000000, which is silently
narrowed to char (is it, in C++?), so then it becomes 64. Which is not
in the set. But 1000001 (65) apparently will be. This is part of a more
general problem, but using narrow function parameters, it's just more
likely to go wrong.
 
>     std::cout << c << " is in identbody\n";
>   }
> }
 
You can simplify it further. Below is a version in C that uses byte-maps
rather than bit-maps, which is OK for small sets. Apart from the
function syntax, it's not so objectionable.
 
However this was simple because I've used a fixed Set type (and assumed
that 'char' is unsigned and that character codes are ASCII). Below the C
code, is reminder of the script version.
 
There, the feature is often used trivially just to do a multiple compare:
 
while ch not in [cr, lf, space, tab] do ...
 
(With byte-code, this can be faster than doing up to four lots of compares.)
 
Expressivity at work...
 
----------------------------------
// C code
 
#include <stdio.h>
#include <string.h>
 
typedef char Set[256];
 
Set identstarter;
Set identbody;
 
void clearset(Set e){
memset(e,0,sizeof(Set));
}
 
void addrange(Set e,int a,int b){
while (a<=b) e[a++]=1;
}
 
void addelem(Set e,int a){ // these should be range-checked, but a bad
e[a]=1; // value is a coding error; passing out-
// out-of-range index to in() is OK
}
 
void subelem(Set e,int a){
e[a]=0;
}
 
int in(int a, Set e){
if (a<0 || a>=256) return 0;
return e[a];
}
 
void printset(char* caption,Set e){
int i;
printf("%s = [",caption);
for (i=0; i<256; ++i)
if (e[i])
if (i>32 && i<127)
printf("%c ",i);
else
printf("0x%02X ",i);
puts("]");
}
 
int main(void) {
int c;
 
clearset(identstarter);
addrange(identstarter,'A','Z');
addrange(identstarter,'a','z');
addelem(identstarter,'_');
addelem(identstarter,'$');
 
memcpy(identbody,identstarter,sizeof(Set));
addrange(identbody,'0','9');
subelem(identbody,'Z');
 
printset("Identstarter",identstarter);
printset("Identbody",identbody);
 
c='Z';
printf("%d\n", in(c, identstarter));
printf("%d\n", in(c, identbody));
}
 
---------------------------------
proc start=
identstarter := ['A'..'Z', 'a'..'z', '_', '$']
identbody := identstarter + ['0'..'9'] - ['Z']
 
c:='Z'
println c in identstarter
println c in identbody
 
end
 
--
bart
Paavo Helde <myfirstname@osa.pri.ee>: Jul 16 05:59PM +0300

On 16.07.2018 17:27, Bart wrote:
 
>> set identbody = (identstarter | Range('0', '9')) & ~Elem('Z');
 
 
> You can simplify it further. Below is a version in C that uses byte-maps
> rather than bit-maps, which is OK for small sets.
[...]
> Set identstarter;
> Set identbody;
[...]
 
> memcpy(identbody,identstarter,sizeof(Set));
> addrange(identbody,'0','9');
> subelem(identbody,'Z');
 
I notice this is 10 lines/statements of *usage* in C as compared to the
2 lines in C++, not to speak about not being able to make the sets const
or constexpr when desired, and not to speak about error-prone use of
sizeof. I would not call it "further simplification".
 
Yes, the full implementation might be simpler in the C version. Who
cares? The implementation is supposed to be written once and used as
many times as possible.
Bart <bc@freeuk.com>: Jul 16 05:33PM +0100

On 16/07/2018 15:59, Paavo Helde wrote:
>>      subelem(identbody,'Z');
 
> I notice this is 10 lines/statements of *usage* in C as compared to the
> 2 lines in C++,
 
Unless it's ultra-simple like the script version, multiple simple lines
can be better than cramming more stuff on one line. But if the line
count matters, then the C can be tweaked so that addrange() etc return
their set parameter. Then it's three lines (plus declarations):
 
addelem(addelem(addrange(addrange(identstarter,'A','Z'),
'a','z'),'_'),'$');
memcpy(identbody,identstarter,sizeof(Set));
subelem(addrange(identbody,'0','9'),'Z');
 
Or two lines if changed to pass and return sets by value.
 
But to go back to an earlier point, this sort of stuff really belongs in
a higher level language (higher level than C++), otherwise the use of it
seems laboured. And the implementation of it (I've glanced at Alf's
headers) has to be reprocessed on each build too.
 
For example, you wouldn't write this even in C++:
 
if (!In(c, Elem(cr) | Elem(lf) | Elem(tab) | Elem(space)) ...
 
like my other script example, because it would be over the top. (And you
can sense the amount of machinery required to make it work, even if it
can eventually be optimised down to little). You would write this:
 
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.
 
(FWIW I don't try to emulate such sets when writing at the level of C. I
use character maps (char[256]) directly without pretending they are
sets. They are initialised via a loop over 0 to 255 so the issue of a
set constructor doesn't arise.
 
As I also said elsewhere you adapt to the language.
 
Having said that, fixed-size sets using bitmaps (and Ranges as a
separate type) /could/ be built-in to a C-type language, and the
handling of them can be made lightweight enough that they could be used
with spontaneity and with little overhead, especially when the set fits
into a machine word.
 
But I haven't done that myself because I don't write enough code in such
a language; I would use the next one up!)
 
--
bart
Paavo Helde <myfirstname@osa.pri.ee>: Jul 16 08:23PM +0300

On 16.07.2018 19:33, Bart wrote:
>> On 16.07.2018 17:27, Bart wrote:
> But to go back to an earlier point, this sort of stuff really belongs in
> a higher level language (higher level than C++), otherwise the use of it
 
I'm not sure if I agree with your definition of "higher level", but I
guess it's a too subjective topic to discuss.
 
> seems laboured. And the implementation of it (I've glanced at Alf's
> headers) has to be reprocessed on each build too.
 
That's true. Compilation time is my main complaint about C++.
 
 
> For example, you wouldn't write this even in C++:
 
> if (!In(c, Elem(cr) | Elem(lf) | Elem(tab) | Elem(space)) ...
 
This basically constructs a constant bitset and performs a lookup. If
the compiler is able to optimize the code so that the bitset
construction happens at compile time only (adding constexpr here and
there might help it to achieve this), this operation becomes a lookup in
a const array and a single code branch.
 
> can sense the amount of machinery required to make it work, even if it
> can eventually be optimised down to little). You would write this:
 
> if (!(c == cr || c == lf || c == tab || c == space)) ...
 
This code has 4 code branching points, so I think it's not given it's
automatically faster. Of course, an optimizer might also see it can
actually ignore these sequence points and create less branchings.
 
> which also has short-circuit evaluation as well as being less likely to
> have people scratching their heads.
 
It looks like you think short-circuiting is good for something in this
example. No, it's not, it will just confuse the CPU branching predictors
if not optimized away.
 
Anyway, you don't use such code at the application level. Why are there
these cr, lf, etc spelled out together? Because there is a concept. The
concept needs to be exposed at the program level so you will write
 
// constructed at compile time
constexpr set whitespace = Elem(cr)|Elem(lf)|Elem(tab)|Elem(space);
 
...
...
if (In(c, whitespace)) { .... }
 
(or you might just use the the standard std::isspace(c,
std::locale("C")) function defined in <locale>; this has the benefit of
being standard).
Ian Collins <ian-news@hotmail.com>: Jul 17 08:13AM +1200

On 17/07/18 00:52, Scott Lurndal wrote:
 
>> Using something like std::unique_ptr to manage the lifetime of an object
>> is a freebie.
 
> So is using a regular pointer and understanding the code.
 
So removing something that has no cost is a sound engineering decision?
 
If code is designed to use smart pointers, especially std::shared_ptr,
removing them is a huge call affecting the core structure of the code.
Using them more efficiently (which is what we did when we had
performance issues) is a much more rational approach.
 
--
Ian.
Vir Campestris <vir.campestris@invalid.invalid>: Jul 16 09:45PM +0100

On 16/07/2018 13:52, Scott Lurndal wrote:
> Ian Collins<ian-news@hotmail.com> writes:
8X
>> Using something like std::unique_ptr to manage the lifetime of an object
>> is a freebie.
> So is using a regular pointer and understanding the code.
 
When the codebase was written by 100 people over 10 years - no,
understanding it isn't free.
 
Andy
Vir Campestris <vir.campestris@invalid.invalid>: Jul 16 09:46PM +0100

> Given C doesn't have exceptions but only explicit returns then remembering
> to call free on a local pointer is hardly onorous.
 
Suppose we have a complex function, that allocates several things,
performs checks on the way, and bails out when it doesn't like a result.
 
Then suppose you want to re-order the checks. You then have to edit the
cleanup before each return:
 
bool dosomething
{
// block 1
type * a = new type;
some checks
if error { free a ; return false; }
 
// block 2
type b = new type;
some more checks
if error { free a ; free b ;return false; }
 
some more code
free a; free b;
return true
}
Now swap block 1 and block 2 around. Don't forget to edit the free
statements.
 
The only way I've seen that maintains your sanity is the Linux kernel
way - use goto as an exception.
 
bool dosomething
{
type * a = null;
type * b = null;
bool ret;
 
a = new type;
some checks
if error { ret = false; goto error }
 
b = new type;
some more checks
if error { ret = false; goto error }
 
some more code
ret = true;
error:

free a; free b;
return ret;
}
 
Compare C++
 
bool dosomething
{
unique_ptr<type> a = std::make_unique<type>();
some checks
if error return false;
 
// block 2
unique_ptr<type> b = std::make_unique<type>();
some more checks
if error return false;
 
some more code
return true
}
 
Andy
Vir Campestris <vir.campestris@invalid.invalid>: Jul 16 09:49PM +0100

On 16/07/2018 18:23, Paavo Helde wrote:
> That's true. Compilation time is my main complaint about C++.
 
We use a thing called Icecream
 
https://github.com/icecc/icecream
 
It spreads the compile load around the office. I normally run my makes
with -J128 - any higher than that and idon't gain, as it takes too long
to send the work out. We have over 300 cores in the pool in our little
branch office.
 
Andy
Bart <bc@freeuk.com>: Jul 16 10:40PM +0100

On 16/07/2018 22:20, Stefan Ram wrote:
> { println( java.lang.Character::isJavaIdentifierStart );
> println( Main::identbody ); }}
 
> transcript
 
It's a mystery how you get from the above to the following:
 
> $ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
> $0123456789ABCDEFGHIJKLMNOPQRSTUVWXY_abcdefghijklmnopqrstuvwxyz
 
This is why expressiveness in the code is important - within reason
otherwise too much will become cryptic. Even with the C code you can see
where and how the 'A' to 'Z' range was defined.
 
(The default printing I use only shows numbers, but will work out the
ranges:
 
[36,65..90,95,97..122]
[36,48..57,65..89,95,97..122]
 
This is handy for rather larger sets:
 
println [1..1000'000'000]
 
Output:
 
[1..1000000000]
 
which would otherwise take too long to print.)
 
--
bart
ram@zedat.fu-berlin.de (Stefan Ram): Jul 16 08:53PM

>But to go back to an earlier point, this sort of stuff really belongs in
>a higher level language (higher level than C++)
 
main.pl6
 
my $identstarter =( 'A' .. 'Z', 'a' .. 'z', '_', '$' ).Set;
my $identbody =( $identstarter ∪ ( '0' .. '9' ))∖( 'Z' );
say $identstarter;
say $identbody;
 
transcript
 
set($ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ a b c d e f g h i j k l m n o p q r s t u v w x y z)
set($ 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y _ a b c d e f g h i j k l m n o p q r s t u v w x y z)
 
ASCII version
 
my $identstarter =( 'A' .. 'Z', 'a' .. 'z', '_', '$' ).Set;
my $identbody =( $identstarter (|) ( '0' .. '9' ) ) (-) ( 'Z' );
say $identstarter;
say $identbody;
ram@zedat.fu-berlin.de (Stefan Ram): Jul 16 09:20PM

>>But to go back to an earlier point, this sort of stuff really belongs in
>>a higher level language (higher level than C++)
>main.pl6
 
In Java, the (nearly!) matching predicates are already
pre-defined, and the challenge is to print them:
 
Main.java
 
public final class Main
{
public static boolean identbody( final int c )
{ return c != 'Z' && java.lang.Character.isJavaIdentifierPart( c ); }
 
public static void println
( final java.util.function.Function<Integer,Boolean> pred )
{ java.util.stream.IntStream.rangeClosed( 32, 126 ).
filter( pred::apply ).
forEach( c -> java.lang.System.out.print(( char )c ));
java.lang.System.out.println(); }
 
public static void main( final java.lang.String[] args )
{ println( java.lang.Character::isJavaIdentifierStart );
println( Main::identbody ); }}
 
transcript
 
$ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
$0123456789ABCDEFGHIJKLMNOPQRSTUVWXY_abcdefghijklmnopqrstuvwxyz
Paul <nospam@needed.invalid>: Jul 16 09:38AM -0400

> IID_ITipInvocation, (void**)&VirKeyboard ) )
 
> Launch( L"/Program Files/Common Files/microsoft shared/ink/TabTip.EXE" );
 
> else VirKeyboard->Toggle( GetDesktopWindow() ), VirKeyboard->Release(); }
 
So you're one of these people then...
 
https://stackoverflow.com/questions/38774139/show-touch-keyboard-tabtip-exe-in-windows-10-anniversary-edition
 
Paul
boltar@cylonHQ.com: Jul 16 01:47PM

On Mon, 16 Jul 2018 06:12:54 -0700 (Seattle)
> Keyboard = FindWindow( 0, L"Microsoft Text Input Application" ),
> Keyboard ? SendMessage( Keyboard, WM_SYSCOMMAND, SC_CLOSE, 0 ) : 0,
> Launch( L"/Windows/SystemApps/InputApp_cw5n1h2txyewy/"
 
Wow, lazy evaluation instead of a proper if() and nested ? operators with comma
seperated multiple statements. And I thought Alfs code was an unmaintainable
mess but he has nothing on this guy.
Jeff-Relf.Me @.: Jul 16 09:02AM -0700

Lewis <g.kreme@gmail.com.dontsendmecopies>: Jul 16 04:05PM

> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> Things like that are the reason why Windows programs suddenly break when
> something is not installed to default location.
 
Are you even able to install microsoft crap in a custom location?
 
Microsoft has been reliant on hard-coded paths since before Windows,
and Windows 10 is no different.
 
--
'Winners never talk about glorious victories. That's because they're the
ones who see what the battlefield looks like afterwards. It's only the
losers who have glorious victories.' --Small Gods
Paavo Helde <myfirstname@osa.pri.ee>: Jul 16 07:31PM +0300

On 16.07.2018 19:05, Lewis wrote:
 
> Are you even able to install microsoft crap in a custom location?
 
> Microsoft has been reliant on hard-coded paths since before Windows,
> 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.
 
Not to speak about missing C: in the original example, the code would
fail every time the current drive happens to be not C:.
 
There are Windows SDK functions for figuring out the locations of such
folders, but apparently if the program happened to work once somewhere
it's not broken.
Jeff-Relf.Me @.: Jul 16 10:04AM -0700

Jeff-Relf.Me @.: Jul 16 10:15AM -0700

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: