Friday, May 1, 2020

Digest for comp.lang.c++@googlegroups.com - 19 updates in 3 topics

red floyd <myob@its.invalid>: May 01 09:45AM -0700

I have a codebase written in c90. We have a once in a lifetime
opportunity to refactor, rearchitect, and rewrite. As such, we
are going to rewrite in C++.
 
Here's my issue. We have two target platforms, one of which has
only a C++03 compiler, the other has a C++11 compiler as well.
Yes I know that both are old language standards, but it's what
we have to work with.
 
The platform with only C++03 support is old, and may stop being
supported. We're trying to decide whether to write in C++11 and
forget the older platform, or use C++03 and support both, and later
transition to C++11.
 
We know the LOE to transition to C++. The question is, what is the
effort to transition a C++03 code base to C++11, including the use of
more modern features to enhance code robustness? I know that you can
throw C++03 at a C++11 compiler and it will build, but as this is a one
time only deal, we want to do things as right as possible the first
time.
 
Any opinions on the level of effort for a "proper" 03 => 11 transition?
Suggestions, etc, are also welcome.
 
Thanks,
 
red floyd
Paavo Helde <eesnimi@osa.pri.ee>: May 01 08:43PM +0300

01.05.2020 19:45 red floyd kirjutas:
 
> I have a codebase written in c90.   We have a once in a lifetime
> opportunity to refactor, rearchitect, and rewrite.   As such, we
> are going to rewrite in C++.
 
Having an opportunity is not a sufficient reason to justify a rewrite
which will inevitable introduce new bugs and destabilize the code base
(unless you have a pretty decent unit test coverage).
 
A valid reason for a rewrite would be a need to significantly expand the
system later. For that it would help if the existing codebase is written
in ways compatible with extensions (abstract base classes, std::function
callbacks, etc). C++03 is actually pretty good for building such
infrastructure.
 
However, if you are going to phase out the old platform anyway soon,
will it benefit at all from this rewrite? If not, then it should be left
to use the C solution.
 
So, the correct answer depends on the actual reason of the rewrite which
you have not disclosed. If this reason is valid also for the old
platform you should rewrite the codebase in C++03 and move on to C++11
later. If the reasons of rewrite do not apply to the old platform you
should leave the old platform to the existing C solution and upgrade the
rest of the system directly to C++11 (or later) as C++ programming has
become much more convenient and safer with C++11.
 
 
red floyd <myob@its.invalid>: May 01 11:04AM -0700

On 5/1/2020 10:43 AM, Paavo Helde wrote:
> should leave the old platform to the existing C solution and upgrade the
> rest of the system directly to C++11 (or later) as C++ programming has
> become much more convenient and safer with C++11.
 
Thanks, Paavo,
 
I understand your concerns, and am normally a huge proponent of the "if
it ain't broke, don't fix it" approach. However, I believe that it is
"broke".
 
The platforms currently share a common codebase. The code has become so
fragile, to the point that we are afraid to fix any bugs, because we are
worried that touching $X will break $Y. It's an accumulation of fifteen
years of ad hoc patches. This is ancient legacy code.
 
We also have some internal framework code that we use, but it's very
rudimentary, and doesn't support all the features we need, which has led
to some very ugly and fragile hacks. The latest version of the
framework, which includes fully fleshed out versions of the features
that we hacked, requires C++.
 
In all fairness to our management, they are giving us a reasonable
amount of time to do the up front design work.
 
The main question here was assuming that we are redesigning in C++ --
which, from signs given by management, appears to be a fait accompli --
Is it worth it to design in C++03, and later migrate to C++11, when the
users of the older platform have migrated to the newer platform? What
are people experiences in moving from C++03 to C++11 (or any modern
variant), and what is the level of effort involved?
 
-- red floyd
Jorgen Grahn <grahn+nntp@snipabacken.se>: May 01 06:44PM

On Fri, 2020-05-01, red floyd wrote:
...
> users of the older platform have migrated to the newer platform? What
> are people experiences in moving from C++03 to C++11 (or any modern
> variant), and what is the level of effort involved?
 
As far as I'm concerned, all the basic, useful features are in C++98.
My C++11 code mostly adds 'auto' and lambdas, but these don't affect
the basic design. I'm more likely to use std::find_if due to the easy
access to functors (lambdas), and less likely to add a lot of typedefs
due to auto.
 
Smart pointers (unique_ptr; shared_ptr if you need those) is another
thing, but as with many library features you can get it from Boost.
 
It also depends on what the programmers are comfortable with. Maybe
you all write C++17 code and would hate to step back in time 20 years?
Or maybe learning how to use a new C++ dialect well would distract
from the porting work?
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Paavo Helde <eesnimi@osa.pri.ee>: May 01 09:48PM +0300

01.05.2020 21:04 red floyd kirjutas:
> fragile, to the point that we are afraid to fix any bugs, because we are
> worried that touching $X will break $Y.  It's an accumulation of fifteen
> years of ad hoc patches.  This is ancient legacy code.
 
I would say the most urgent need for you is to develop a comprehensive
automatic test suite. It would help with avoiding $X breaking $Y, it
would help (a lot!) when rewriting the code in C++, and it will help (a
lot!) when later developing the system further.
 
I know it does not sound pleasant to put all developers (QA, if you have
one, is probably not qualified enough) writing unit/integration tests
for a couple of months, instead of writing new shiny C++ code, but this
is actually the only way to come out of such a situation and save money
in the long run.
 
> which, from signs given by management, appears to be a fait accompli --
> Is it worth it to design in C++03, and later migrate to C++11, when the
> users of the older platform have migrated to the newer platform?
 
This depends on whether these people need feature $Y before migrating to
the newer platform.
 
>   What
> are people experiences in moving from C++03 to C++11 (or any modern
> variant), and what is the level of effort involved?
 
You actually don't migrate the codebase from C++03 to C++11, this is not
needed for anything. You just starting writing the new code (and any
local refactoring of old code) with C++11 means as soon as the build
process has switched on -std=c++11 (or equiv). So in this sense the
transition should be smooth.
 
In C++03, beware to not use things removed in later C++ standards like
throw specifications, 'register' keyword, std::bind1st, etc.
 
 
 
 
 
 
Paavo Helde <eesnimi@osa.pri.ee>: May 01 09:52PM +0300

01.05.2020 21:48 Paavo Helde kirjutas:
> In C++03, beware to not use things removed in later C++ standards like
> throw specifications, 'register' keyword, std::bind1st, etc.
 
Oh, and avoid std::auto_ptr of course. Use Boost smart pointers or
develop your own, that's not so complicated.
Jorgen Grahn <grahn+nntp@snipabacken.se>: May 01 09:17PM

On Fri, 2020-05-01, Paavo Helde wrote:
...
 
> I know it does not sound pleasant to put all developers (QA, if you have
> one, is probably not qualified enough) writing unit/integration tests
> for a couple of months, instead of writing new shiny C++ code,
 
Seconded. You feel so stupid when you know how you want to refactor
the code, but have no way to tell if it still works afterwards.
 
> but this is actually the only way to come out of such a situation
> and save money in the long run.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
"Öö Tiib" <ootiib@hot.ee>: May 01 02:18PM -0700

On Friday, 1 May 2020 19:45:00 UTC+3, red floyd wrote:
> only a C++03 compiler, the other has a C++11 compiler as well.
> Yes I know that both are old language standards, but it's what
> we have to work with.
 
Platforms that lag behind do often have some quirks in their
implementations of those older standards too. Common code
can be fine but some trick (like used in boost) may refuse to
compile or act in non-conforming manner.
 
> time.
 
> Any opinions on the level of effort for a "proper" 03 => 11 transition?
> Suggestions, etc, are also welcome.
 
There were next to none silently breaking changes between C++03 and
C++11. Vast majority of C++03 code did build and run as C++11 too.
There can be some undefined behaviors that start to manifest
differently, but it is generally good that these will be noticed.
Additionally there is Clang-Tidy that actively suggests what to
refactor in C++03 code.
 
So I think that rewriting C90 -> C++03 is large effort because the
idioms and design strategies of those languages are different.
Migrating C++03 -> C++11 is order of magnitude smaller effort.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: May 01 02:40PM -0700

> time.
 
> Any opinions on the level of effort for a "proper" 03 => 11 transition?
> Suggestions, etc, are also welcome.
 
What if you transition directly from C90 to C++11 and just don't
support the new codebase on the old platform? Can you continue
supporting only the old C codebase on the old platform until it's
retired, while using the new C++11 codebase on the new platform?
You know the old C90 code still works; is that good enough for
*temporary* support?
 
On the other hand, supporting two different codebases simultaneously
isn't going to be free.
 
On the gripping hand, having the old and new codebases in production
use at the same time might help weed out inconsistencies.
 
How sure are you that the old target platform is really going away?
Is there a risk that you'd be stuck supporting the C90 codebase
indefinitely?
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
red floyd <myob@its.invalid>: May 01 03:52PM -0700

On 5/1/2020 2:17 PM, Jorgen Grahn wrote:
> the code, but have no way to tell if it still works afterwards.
 
>> but this is actually the only way to come out of such a situation
>> and save money in the long run.
 
That's one of the pluses of a refactor on this scale. For historical
reasons, and then because of the high coupling factor from the patches,
it was really impossible to have an automated unit test suite. By
refactoring on this scale, we can write the unit tests as we go.
 
A little more historical background, this was a proof-of-concept that
marketing grabbed and said "OK, it's the product". So it didn't have
the in-depth design and review that it would today.
Richard Damon <Richard@Damon-Family.org>: Apr 30 08:43PM -0400

On 4/30/20 5:18 PM, Keith Thompson wrote:
> int *class = malloc(sizeof 'A');
> }
> would be worth the implementation effort.
 
Wouldn't that be illegal as C code, as C requires file scope
initializers to be constants, so we never get to the type of 'A';
 
Now make that
 
extern "C" {
extern int foo[sizeof 'A'];
}
 
and you have a different problem.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Apr 30 07:00PM -0700

>> would be worth the implementation effort.
 
> Wouldn't that be illegal as C code, as C requires file scope
> initializers to be constants, so we never get to the type of 'A';
 
Yes, good point. Make it
 
extern "C" {
int class = sizeof 'A';
}
 
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
Juha Nieminen <nospam@thanks.invalid>: May 01 07:26AM

> in C. Since it is C++ that wants to include C headers, and not the
> other way around, it is C++ that should more of the heavy lifting
> needed to get that to happen.
 
I'm not sure that solves the problem I presented.
 
Suppose you have something like this in a typical C header:
 
//---------------------------------------------------
struct Data
{
int value1;
double value2;
float table[10];
};
 
double handleData(const Data* data);
//---------------------------------------------------
 
(I omitted the typical "#ifdef __cplusplus extern "C"" part
for brevity.)
 
In the C++ code you need to be able to call that function, and
in order to do that you need a way to create and handle instances
of that struct. This could become difficult if there was a complete
incompatibility between C++ and C. Suddenly you couldn't, possibly,
instantiate that struct, initialize its members, etc etc, if the
syntax (and perhaps even semantics) to do so would be wildly different
in C++.
 
You would need some kind of interoperatibility syntax between
C data types and C++ data types and code.
 
Also consider how some C library headers may declare preprocessor
defines that have something more than just integer or string literals.
They may contain "inline" code. This code would be inserted into your
C++ code if you use those macros. Obviously if C++ syntax were wildly
different from C syntax, it would completely exclude the possibility
of using such macros in such headers.
Juha Nieminen <nospam@thanks.invalid>: May 01 07:31AM


>> Of course nowadays we can declare it as 'inline' which solves the problem,
>> but that has to be explicitly specified, and it needs compiler support.
 
> What's difference if `inline`?
 
If I understand correctly, an 'inline' variable will be dealt with
the same way as an 'inline' function: If it ends up being actually
instantiated (ie. not actually inlined) and thus may appear in more
than one object file, the linker will be instructed to just choose
one of those instances and discard the rest. All uses of that object
or function will refer to that one singular instance (rather than
multiple ones).
 
(This means that, for example, a pointer to the object/function
will always be the same accross the entire program, rather than
every compilation unit getting its own separate pointer value.)
Paavo Helde <eesnimi@osa.pri.ee>: May 01 10:31AM +0300

01.05.2020 02:19 James Kuyper kirjutas:
> you need to more precisely specify what you mean by "C semantics".
 
> If the C++ standard were modified as you describe, how could such code
> be re-written?
 
+1
 
Restricting extern "C" to pure C would make it pretty hard to write
shared library plugins in C++ as currently extern "C" is the only way to
make standard and predictable function names for shared library symbol
lookup.
David Brown <david.brown@hesbynett.no>: May 01 06:24PM +0200

On 01/05/2020 09:31, Juha Nieminen wrote:
 
> (This means that, for example, a pointer to the object/function
> will always be the same accross the entire program, rather than
> every compilation unit getting its own separate pointer value.)
 
A vital point to mention is that all definitions of the object must be
the same, so that it doesn't matter which of the objects the linker uses
and which it discards. (Again, just like inline functions.)
 
The addition to the language is so that you can conveniently put large
object definitions (whether const or not) in a header without needing an
accompanying .cpp file or playing tricks with templated functions with
static variables.
Ralf Goertz <me@myprovider.invalid>: May 01 08:19AM +0200

Am Thu, 30 Apr 2020 22:58:54 +0300
> > really be a bug?
 
> FWIW, compiling this program with my Cygwin gcc 9.3.0 in Windows
> works as expected (copies the file).
 
Interesting. I used msys2 64bit. So this is more likely to be an msys2
bug then?
 
> (including non-obvious ones like virus scanners) so that they cannot
> be deleted (though in this case the error message should probably be
> something like "Access denied").
 
Yeah I know that, but this is not the case here. I used
 
$ touch foo
$ fs_copy
$ fs_copy
 
with fs_copy being the program above and its second execution threw.
(Also in a powershell btw.) Then after deleting "foo" and "bar" I used
 
$ touch foo
$ cp foo bar
$ cp foo bar
 
which worked fine.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 01 08:28AM +0200

On 01.05.2020 08:19, Ralf Goertz wrote:
> $ cp foo bar
> $ cp foo bar
 
> which worked fine.
 
Is it /consistently/ reproducible?
 
During the last year or so Microsoft has introduced a bug-nest somewhere
in the high level file system interfaces, so that some operations such
as obtaining directory listings, involve inordinately long pauses --
usually one long pause (which is not disk spin-up) at the start.
 
They have a history of introducing such pauses for Odin knows what
reason, e.g. for listing network connections via `netstat`, or listing
open file handles via `openfiles`, or for that matter, for moving, via
Explorer, a directory from one place to another place on the same drive,
but via a logical drive (which shouldn't matter, it should be instant
anyway). Historically it seems to me, but I /could/ be wrong, that these
artifical slow-downs have to do with some manager or group of managers
at Microsoft saving himself/themselves work and face by sabotaging the
system instead of being responsible for a fix of something.
 
- Alf
Ralf Goertz <me@myprovider.invalid>: May 01 08:43AM +0200

On Fri, 1 May 2020 08:28:51 +0200
> > $ cp foo bar
 
> > which worked fine.
 
> Is it /consistently/ reproducible?
 
Yes. I noticed it about a month ago after porting my linux program to
windows. The program is in heavy use by my colleagues and they always
have to delete the files before starting it. It was only yesterday that
I started to investigate it further.
 
> work and face by sabotaging the system instead of being responsible
> for a fix of something.
 
> - Alf
 
I wouldn't know but I doubt it. As I said there is no problem copying
and overwriting files by other means.
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: