- Text editor project in C - 7 Updates
- No, C is not a simple language - 17 Updates
- std::bind with member functions and C++20 - 1 Update
| 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:
Post a Comment