Monday, April 26, 2021

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

wij <wyniijj@gmail.com>: Apr 25 08:34PM -0700

> FORTRAN or C. But that wasn't even a question as I was particularly asking who
> wants to migrate/translate/switch from C++ product/code base to any of those
> now and why as I know outright totally none cases.
 
Who? Who can say that specifically except themselves?
 
For many companies/application users, a program is just a program of which
the language written is irrelevant. The product of many companies in my country
are physical things. They hire programmers because of the functions needed
change frequently in various production phase/line. In their view, it the
question of changing programs, not programming languages. Thus, the hired
programmers have to adapt, probably endup with script/mixed languages.
 
Qt is the thing I know better because I had a commercial license (Qt3, I just use
several basic elements), they send me email regularly. That Qt itself is in C++
probably will not change, but their products seems changing from pure C++
codes to QML and tool set. In the end, I fear the C++ core part may shrink accordingly.
Who? you ask them.
Juha Nieminen <nospam@thanks.invalid>: Apr 26 05:22AM

> because it will be always needed; it is realloc'ed when needed, and
> freed by the OS when the program terminates. This is abvious for anyone
> reading C.
 
The main point is that malloc()'ing something and not free()'ing it is
bad practice. Not only does it teach you bad habits, it teaches other
people reading the code this same bad habit. This is especially
egregious in code that's being used for didactic purposes out there,
for thousands and thousands of students to see.
 
This potentially (quite potentially) will lead to people learning the
bad habit and then not bothering to free() what they malloc() in
situations where it actually becomes detrimental. In loops where the
amount of leaked memory will start increasing and increasing indefinitely.
When the code is complicated enough, and there are hundreds and hundreds
of such non-freed mallocs all over the place, in complex code, it becomes
a nightmare to fix.
 
On that note, I don't think the term "freed by the OS" should be used
in this context. In fact, I would say that anybody who makes that claim
doesn't actually understand how malloc() and free() work, and what their
relationship is with the OS (at least in most operating systems).
 
It makes it sound like every time you call malloc(), it will make an OS
call, which will make the OS allocate a block of memory of that size
(which wasn't allocated for the program before), and that the OS itself
keeps track of these possibly thousands and thousands, sometimes millions
of tiny allocations (think of a linked list, or a binary tree, where each
node is allocated individually), and once the program terminates, the OS
will "garbage-collect" all these tiny individual allocations and free
them again for other programs to use. In other words, as if the OS called
free() for you, for each malloc() you did (and didn't explicitly free),
when the program ends.
 
More particularly, the claim makes it sound like if the OS didn't
"garbage-collect" all the malloc()s you did, which you didn't free()
yourself, they would be permanently allocated, never to be reusable by
any other program.
 
Of course that's not how it works. In this sense the claim is incorrect.
Juha Nieminen <nospam@thanks.invalid>: Apr 26 05:29AM

> improvement. The global 'int pflag' here, for example, would suck no
> matter how you rename it. If it's changed to an enum, and wrapped and
> documented in a struct EditorState[1], it doesn't need to be renamed.
 
I don't agree. Code becomes more readable when cryptic and non-descript
names are changed to names that make the code more self-documenting,
even without any other changes.
 
As an example, suppose you see a line of code like this:
 
convert(a, b);
 
Well, that doesn't say much. We have absolutely no way of knowing what
it does. But suppose the function were renamed to:
 
convert_string_to_wstring(a, b);
 
Ah, now we are talking. Now it actually says what it's doing.
There's of course still the minor problem that we don't know which
parameter is the string, and which one is the wstring. But we can also
rename the variables:
 
convert_string_to_wstring(dest, src);
 
And suddenly, a line of code that told us absolutely nothing, now
tells us everything.
 
(The above example is actually based on actual production code I have seen.)
jacobnavia <jacob@jacob.remcomp.fr>: Apr 26 10:00AM +0200

Le 26/04/2021 à 07:22, Juha Nieminen a écrit :
> people reading the code this same bad habit. This is especially
> egregious in code that's being used for didactic purposes out there,
> for thousands and thousands of students to see.
 
1) The code was presented as a test text for a GREP assignment. The
assignment was to rewrite GREP and test it with the ed.c text file.
 
Since you spoke of a simple editor project in C, I showed you one
written 50 years ago of just 1700 lines. It compiles and runs 50 years
later. Please show me a complex program in C++ from 2000 that compiles
unmodified and runs today.
 
2) In many applications, the information gathered and stored using
malloc will be used until the exit of the program: in a compiler, for
instance, or in a text editor. A good strategy is to malloc and never
free, since all the memory is used until the program exits. This
simplifies and accelerates the program.
 
> This potentially (quite potentially) will lead to people learning the
> bad habit and then not bothering to free() what they malloc() in
> situations where it actually becomes detrimental.
 
Maybe, maybe not. I suppose that people that want to program are able to
see when to use malloc and free, when to use just malloc,never freeeing
and letting the OS free everything at exit.
 
> When the code is complicated enough, and there are hundreds and hundreds
> of such non-freed mallocs all over the place, in complex code, it becomes
> a nightmare to fix.
 
This has a simple fix (that I have used a lot):
1) Replace all malloc calls by calls to Mymalloc
2) Write a simple function Mymalloc that allocates from a heap
3) Free the heap when the program terminates. This way, a program that
never freed anything can be included into a larger project that needs
the free().
 
 
> in this context. In fact, I would say that anybody who makes that claim
> doesn't actually understand how malloc() and free() work, and what their
> relationship is with the OS (at least in most operating systems).
 
I think that you are the one that doesn't understand. Let's see:
 
> It makes it sound like every time you call malloc(), it will make an OS
> call, which will make the OS allocate a block of memory of that size
> (which wasn't allocated for the program before),
 
 
This is exactly what happens. The OS allocates a block of memory that
malloc/free manages. All mallocs use some API for calling the OS.
 
and that the OS itself
> them again for other programs to use. In other words, as if the OS called
> free() for you, for each malloc() you did (and didn't explicitly free),
> when the program ends.
 
The OS frees the heap of the application (conceptually).
> "garbage-collect" all the malloc()s you did, which you didn't free()
> yourself, they would be permanently allocated, never to be reusable by
> any other program.
 
????
 
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Apr 26 01:25AM -0700

On 4/25/2021 12:02 PM, James Kuyper wrote:
 
> I couldn't help thinking how weird that statement would sound outside of
> a computer programming context. I imagined someone shying away in terror
> when someone else used scissors to cut off a piece of thread. :-)
No man, don't cut the cord, join it... ;^)
 
Big time! :^D
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Apr 26 01:26AM -0700

On 4/25/2021 12:02 PM, James Kuyper wrote:
 
> I couldn't help thinking how weird that statement would sound outside of
> a computer programming context. I imagined someone shying away in terror
> when someone else used scissors to cut off a piece of thread. :-)
 
AHAHAHA!
Juha Nieminen <nospam@thanks.invalid>: Apr 26 09:57AM

> Since you spoke of a simple editor project in C, I showed you one
> written 50 years ago of just 1700 lines.
 
Not comparable because my entire point was about how laborious and
error-prone it is to handle *dynamically allocated* (and length-changing)
strings. The program you posted uses a static array for the lines,
with a fixed maximum length. Not really comparable.
 
> It compiles and runs 50 years
> later. Please show me a complex program in C++ from 2000 that compiles
> unmodified and runs today.
 
Can you show me a C++ program from 2000 that doesn't?
 
> instance, or in a text editor. A good strategy is to malloc and never
> free, since all the memory is used until the program exits. This
> simplifies and accelerates the program.
 
For starters, allocating some kind of memory buffer that gets reused in
the program for many things doesn't stop you from freeing it at the end.
 
Secondly, that's not really an option for a text editor where you have
to load a text file into RAM and allow the user to edit its lines (by eg.
adding content to them). You can't do this with one single allocation.
(You can read the file into RAM with one single allocation, but you can't
then support adding stuff to it without reallocation. Moreover, if it's
a text editor you probably want to allocate each line individually to
allow them to be grown efficiently, without having to realloc the entire
thing.)
 
> 3) Free the heap when the program terminates. This way, a program that
> never freed anything can be included into a larger project that needs
> the free().
 
That doesn't make any difference. If you are leaking memory in a loop,
your program will start consuming more and more RAM until it runs
out of it. It makes no difference whether you use your own allocator
for this or not, if you never free the memory blocks that you don't
need anymore.
 
>> (which wasn't allocated for the program before),
 
> This is exactly what happens. The OS allocates a block of memory that
> malloc/free manages. All mallocs use some API for calling the OS.
 
No, it's not. malloc() and free() are (typically) handled by the C
runtime library. This library will make a system call to ask for more
heap space only if needed. If a malloc() can be done within the current
heap, it won't ask the OS for more.
 
The only thing that the OS sees is the heap expansion requests (and
possibly heap shrinking requests). It doesn't see the individual
mallocs and frees. It doesn't know nor care which parts of the heap
are "unused" and which are "in use" by the program internally.
 
>> free() for you, for each malloc() you did (and didn't explicitly free),
>> when the program ends.
 
> The OS frees the heap of the application (conceptually).
 
That's what I said. It doesn't care about any "mallocs" or "frees" of
the program. It just sees a heap, and doesn't care what the program
does with it. When the program ends, the OS reclaims that heap.
Juha Nieminen <nospam@thanks.invalid>: Apr 26 04:47AM

>>to worry about it or change its interface according to such requirements.
 
> Or you could just use std::list. The point was to show that they understood
> basic data structures and memory allocation.
 
If I were interviewing someone for a position of C programmer, I would be
most interested in knowing that he understands the dynamic memory management
problems in the language.
 
A linked list is an extraordinarily trivial data container. Naturally if
the interviewee asks "what's a linked list?" then I wouldn't hire such a
person. However, when the position is for a C programmer in particular,
I *would* be more interested in him understanding the memory management
portion more than the linked list part. If the interviewee started asking
such questions as I presented (ie. what the requirements are for the
list, whether it should be generic or just contain a particular type, etc.)
that would certainly be a positive mark, because he clearly understands the
intricacies of C.
 
If it were for a C++ position, an answer of a type "I would primarily use
std::list, but if I had to implement the list data structure muself,
I would do it like this..." would score highly.
 
>>that might themselves require memory management).
 
> If you need a linked list you need a linked list. Using an array or hash
> would be the wrong answer.
 
It's actually relatively rare to need linked lists. There exist
algorithms (ones being actually used out there) where a linked list is
actually the most efficient data container, but in my experience they
tend to be rare.
Juha Nieminen <nospam@thanks.invalid>: Apr 26 04:55AM

> replying, a beginner's struggles with string manipulation was used as a
> proxy for the argument that C, although much smaller as a language than
> C++, is not simpler than C++ and that C++ is easier to learn.
 
I actually made no point about learning. My point was about usage.
 
It doesn't make a difference whether it's a complete beginner or someone
who has programmed with both languages for decades. I myself have done
the latter, and I still find C++ significantly easier and simpler to
program with. When it comes to dynamic strings, I'll use std::string.
It's not just some kind of "beginner tool" that's useful only until
you learn the "better way". std::string *is* the better way. And it
so happens to also be the more beginner-friendly way.
 
(That doesn't mean I never use char* to do things with strings.
Of course I do. I know quite well how both ways work internally, and
when it's better to use which. Use the best tool for the task at hand.)
Juha Nieminen <nospam@thanks.invalid>: Apr 26 05:01AM

> I have seen successful large projects in C, mostly back end services.
 
Of course there are successful C projects. The Linux kernel is written
almost entirely in C. I haven't really looked at the source code but I
wouldn't be surprised if it's relatively clean and easy to undrestand
(at least for the most part). Many large projects like gcc and clang
are written mostly in C. There are many other examples.
 
The question is not really whether a large project *can* be written
in C.
Juha Nieminen <nospam@thanks.invalid>: Apr 26 05:04AM

> You cannot use memcpy/memmove in 'pure' C++.
 
Why not? They are standard C++ library functions.
 
> As to the memory allocation issue, in extreme cases (real programs will encounter),
> e.g. many string objects, or one long string, one might even need to use zero-terminate
> c-string directly and RAII becomes a hinder.
 
That doesn't make any sense. RAII becomes a hinder for zero-terminating C strings?
What are you talking about?
Paavo Helde <myfirstname@osa.pri.ee>: Apr 26 09:41AM +0300

23.04.2021 14:58 wij kirjutas:
 
> std::string provides "helper functions" to manipulate "C-string"
> (precisely speaking, this was an error of 'pure' C++, we are now actually
> talking about an erroneous feature of C++), does not mean C is ugly.
 
What? Making a C++ feature interoperable with C is an error?
 
One might argue that std::string class is too large and attempts to do
too many things, and there might be a bit truth in it. That's why we now
have other classes like std::string_view. On the other hand, all this
large interface is sometimes needed, I think the only member function I
have never used is std::string::at().
 
 
> Helper functions(or macro/template) come with cost (user usually do not care,
> but note that it can accumulate) and can not cover all cases.
 
I have no idea what you mean here. Arguably the whole C string
manipulation is done by helper functions like strcat().
 
> You cannot use
> memcpy/memmove in 'pure' C++.
 
What? Technically memcpy() is the most correct way to do type punning in
C++, for example. How come the most correct way to do something cannot
be used?
 
I guess you wanted to say that memcpy() may not be used with non-trivial
C++ objects. That's true, but what is the point? In C you may not call
free() with an address of a local variable, this does not make free()
unusable.
 
And what's the relation to the string processing? The std::string move
operator will easily beat any memcpy() or memmove() of string contents,
with the extra bonus that it is much less error prone.
 
 
> As to the memory allocation issue, in extreme cases (real programs will encounter),
> e.g. many string objects, or one long string, one might even need to use zero-terminate
> c-string directly and RAII becomes a hinder.
 
Here I can not even guess what crossed your mind when writing these
sentences. In case you are a not aware, all strings hold be std::string
are already automatically zero-terminated nowadays.
 
If you want to really attack C++ over C you should express yourself more
coherently. And choose some other topic, string processing is not an
area where you can win, or even look credible.
MrSpook_531q@dr4t0dkj168m4ml.tv: Apr 26 08:13AM

On Mon, 26 Apr 2021 04:47:02 +0000 (UTC)
 
>If I were interviewing someone for a position of C programmer, I would be
>most interested in knowing that he understands the dynamic memory management
>problems in the language.
 
That comes as part of creating a linked list in C - ie malloc the list
element and then freeing it and resetting pointers.
 
>A linked list is an extraordinarily trivial data container. Naturally if
 
It might be a trivial container, but implementing it from scratch isn't as
it has a few gotchas particularly doubly linked ones. Anyway as i've said, it
was a job interview, not a comp sci exam.
 
>the interviewee asks "what's a linked list?" then I wouldn't hire such a
>person.
 
Well obviously not.
 
>If it were for a C++ position, an answer of a type "I would primarily use
>std::list, but if I had to implement the list data structure muself,
>I would do it like this..." would score highly.
 
Indeed.
 
>> If you need a linked list you need a linked list. Using an array or hash
>> would be the wrong answer.
 
>It's actually relatively rare to need linked lists. There exist
 
Queues. You can implement them using arrays but that would be very inefficient.
Obviously in C++ there are already queue containers, but in C you'd use
a linked list.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Apr 26 01:22AM -0700


> Queues. You can implement them using arrays but that would be very inefficient.
> Obviously in C++ there are already queue containers, but in C you'd use
> a linked list.
 
Check this queue out:
 
https://groups.google.com/g/lock-free/c/acjQ3-89abE/m/a6-Di0GZsyEJ
 
;^)
Robert Latest <boblatest@yahoo.com>: Apr 26 08:49AM

Juha Nieminen wrote:
> on C, and wanted to create a simple text editor, which would read a
> text file, allow the user to edit the text in several ways, and to
> save the file.
 
Doesn't sound like an appropriate project for a beginner, much less for a
beginner in C.
 
Given a problem and the platform on which it should be solved, one should
select the appropriate language. There are many to choose from.
 
--
robert
Robert Latest <boblatest@yahoo.com>: Apr 26 09:02AM

["Followup-To:" header set to comp.lang.c.]
Juha Nieminen wrote:
> The problem with C is that anything that requires manual construction and
> destruction will "contaminate" (can't think of a better word) anything that
> uses that first thing, with the same requirements. All the way down.
 
Of course it does. If you insist on doing it in C, it's best to define
functions new_xxx and free_xxx for each type xxx, and make sure that free_yyy
is called from free_xxx if the xxx type contains dynamically allocated objects
of type yyy. It's really not hard, just requires a bit of typing, but it's a
tremendously helpful exercise especially for a beginner.
 
BTW if this concept is new or "The problem" for you, I don't believe you have
much experience with C.
 
> and destruction, and you put it as a member of a struct, suddenly that
> struct "inherits" the same requirement. Use that struct in yet another
> struct and that, too, will "inherit" the same requirement.
 
 
Trivially dealt with, see above.
 
> other structs, no dynamic memory allocation in sight so far. Then you need
> to add dynamic memory allocation to one of the structs (that's being used
> as a member of other structs etc) and suddenly all that code breaks.
 
...as it would in any language if you change the architecture of your design
without making the appropriate changes where needed.
 
> now "inherited" the need for manual construction and destruction (even though
> they were never designed for that initially), you'll have to go and modify
> those millions of lines to follow suit.
 
If that's a problem for you, just don't use a strongly typed language.
 
> Not so in C++, if you design your structs/classes correctly.
 
Your argument above is based on NOT designing your data structures correctly in
C, and now you say C++ handles better but only IF you do it correctly? Doesn't
make sense.
 
Even when trying to do everything explicitly right in C you will make mistakes.
Or I will, anyway. I've found valgrind to be an invaluable tool when debugging
C code.
 
I'm very happy with teaming up C and Python. Low level ultrafast stuff in C
extension, high level OO garbage-collected stuff in Python. In the 90's I did a
largish project in C++ and never grew to like it much.
 
--
robert
MrSpook_9p05k3C69@xr34.gov.uk: Apr 26 09:03AM

On Mon, 26 Apr 2021 01:22:17 -0700
>> a linked list.
 
>Check this queue out:
 
>https://groups.google.com/g/lock-free/c/acjQ3-89abE/m/a6-Di0GZsyEJ
 
 
iIt doesn't show the definition of XADD, LOAD or STORE so who knows how
efficient it is or isn't. But I'd be surprised if its better than a list.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Apr 26 02:17AM -0700


>> https://groups.google.com/g/lock-free/c/acjQ3-89abE/m/a6-Di0GZsyEJ
 
> iIt doesn't show the definition of XADD, LOAD or STORE so who knows how
> efficient it is or isn't. But I'd be surprised if its better than a list.
 
XADD is an atomic fetch-and-add RMW, load and store are atomic loads and
stores.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Apr 26 02:22AM -0700


>> https://groups.google.com/g/lock-free/c/acjQ3-89abE/m/a6-Di0GZsyEJ
 
> iIt doesn't show the definition of XADD, LOAD or STORE so who knows how
> efficient it is or isn't. But I'd be surprised if its better than a list.
 
Actually its faster than lock-free queues comprised of linked nodes, but
it is bounded. So, in a sense, its not really fair to compare it to a
linked node queue. Its faster, but oh well, its bounded.
MrSpook_i4zl8mHy@0tr9r.eu: Apr 26 09:23AM

On Mon, 26 Apr 2021 02:17:20 -0700
>> efficient it is or isn't. But I'd be surprised if its better than a list.
 
>XADD is an atomic fetch-and-add RMW, load and store are atomic loads and
>stores.
 
OK, but the size of cells[] is fixed at start up which makes it useless for
any serious use case aside from perhaps in embedded systems where limits
need to be set which means the cost of resizing the array doesn't come into
it. Plenty of things can be implemented cheaply if you hard limit the max
size at the start.
Robert Latest <boblatest@yahoo.com>: Apr 26 09:24AM

["Followup-To:" header set to comp.lang.c.]
jacobnavia wrote:
> Just have a constructotr and never free anything. Then link with Boehm's
> GARBAGE COLLECTOR and be done with it!
 
Whan I find myself in a situation where explicitly freeing resources becomes
unwieldy I start thinking about using another language than C (which, like
i.e. Python, comes with garage collection).
 
If you're too lazy to use free(), you should also be too lazy to use malloc()
or to declare your variables. Better to use a language where you don't have to
do any of it.
 
--
robert
Robert Latest <boblatest@yahoo.com>: Apr 26 09:27AM

["Followup-To:" header set to comp.lang.c.]
jacobnavia wrote:
> taxi driver... "Don't you get bored passing gears all day?"
 
> And he acknowledged: yes, My arm hurts at the end of the day. Maybe you
> are right, should get an automatic...
 
The C-with-GC analogy would be to first buy a stick shift car and then
expensively retrofit it with an automatic transmiassion (probably voiding the
warranty in the process). Better to buy a car that already comes with automatic
transmission.
 
--
robert
Juha Nieminen <nospam@thanks.invalid>: Apr 26 09:37AM

> Queues. You can implement them using arrays but that would be very inefficient.
 
std::deque doesn't use linked lists, and I don't think it's very inefficient.
Juha Nieminen <nospam@thanks.invalid>: Apr 26 09:43AM

> Your argument above is based on NOT designing your data structures correctly in
> C, and now you say C++ handles better but only IF you do it correctly? Doesn't
> make sense.
 
Are you telling be that every single time you create a struct in a C program
you always write a "constructor" and "destructor" for it, just in case that
some time in the future they might start requiring them?
 
Well, even if you actually do, my point stands: In C++ you don't need to do
that.
MrSpook_2p4eH@0kd0c4bkwzno.biz: Apr 26 07:40AM

On Sun, 25 Apr 2021 10:07:33 -0700 (PDT)
>unstructured code vomits (kind of BASIC-programs) and classes are
>inconvenience for them. They are usually embittered and confused why
>so few people like their exquisite brand of "taste".
 
And others are too stupid to see how the 1st example could have been tidied
up to be a 1 line initialisation. But I'll leave that for you to figure out
genius.
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: