- Available C++ Libraries FAQ - 1 Update
- incompatible types in assignment - 13 Updates
- Worst thing about 2020 C++ - 9 Updates
Nikki Locke <nikki@trumphurst.com>: Aug 14 10:23PM Available C++ Libraries FAQ URL: http://www.trumphurst.com/cpplibs/ This is a searchable list of libraries and utilities (both free and commercial) available to C++ programmers. If you know of a library which is not in the list, why not fill in the form at http://www.trumphurst.com/cpplibs/cppsub.php Maintainer: Nikki Locke - if you wish to contact me, please use the form on the website. |
RM <robert_magdziarz@wp.pl>: Aug 14 02:16PM +0200 I am learning C++. I have the code: class strvector : public std::vector<std::string> { ... }; class obfuscator { ... strvector (*identifiers)[INDEX_WHAT_NUM], (*random_identifiers)[INDEX_WHAT_NUM], (*framework_identifiers)[INDEX_WHAT_NUM]; ... obfuscator() { ... identifiers = new strvector[INDEX_WHAT_NUM]; random_identifiers = new strvector[INDEX_WHAT_NUM]; framework_identifiers = new strvector[INDEX_WHAT_NUM]; ... } ~obfuscator() { delete [] identifiers; delete [] random_identifiers; delete [] framework_identifiers; } ... }; And I have errors: src/obfuscator.hpp: In constructor 'obfuscator::obfuscator()': src/obfuscator.hpp:75:51: error: incompatible types in assignment of 'strvector*' to 'strvector [5]' identifiers = new strvector[INDEX_WHAT_NUM]; ^ src/obfuscator.hpp:76:58: error: incompatible types in assignment of 'strvector*' to 'strvector [5]' random_identifiers = new strvector[INDEX_WHAT_NUM]; ^ src/obfuscator.hpp:77:61: error: incompatible types in assignment of 'strvector*' to 'strvector [5]' framework_identifiers = new strvector[INDEX_WHAT_NUM]; How to correct my code? |
Sam <sam@email-scan.com>: Aug 14 08:43AM -0400 RM writes: > ... > strvector (*identifiers)[INDEX_WHAT_NUM], (*random_identifiers) > [INDEX_WHAT_NUM], (*framework_identifiers)[INDEX_WHAT_NUM]; identifiers is an array. It pops into existence all of its own. Ditto for the others. > identifiers = new strvector[INDEX_WHAT_NUM]; > random_identifiers = new strvector[INDEX_WHAT_NUM]; > framework_identifiers = new strvector[INDEX_WHAT_NUM]; These class members already exist. They don't need to be `new`ed or deleted. Now, you do need to `new` each one of these INDEX_WHAT_NUM strvectors, individually, one by one. > delete [] random_identifiers; > delete [] framework_identifiers; > } And then delete each one, one by one in the destructor. But really, let me let you in on a very closely held secret. Promise not to tell anyone, this secret that's known only by a handful of C++ gurus in the world: In modern C++, there is rarely a need to new or delete anything. Rather, you use containers do all that work for you. Or, in case of fixed-size arrays, just declare them: strvector identifiers[INDEX_WHAT_NUM], random_identifiers[INDEX_WHAT_NUM], framework_identifiers[INDEX_WHAT_NUM]; Its unclear whether strvector has a default constructor or not. Just declaring a plain array requires a default constructor. Otherwise, simply use std::vector, with a smart use of `reserve()` to avoid needless copying, and let std::vector do all the work of new-ing and delete-ing, all by itself. Its, of course, important to understand how dynamic memory allocations work. But it is rarely needed in most simple use cases. > How to correct my code? Get rid of new and delete, complete. Use vectors, or lists, or some other container that will do this for you. |
Bonita Montero <Bonita.Montero@gmail.com>: Aug 14 02:57PM +0200 Although there might be workarounds the issue of the OP is still interesting. |
RM <robert_magdziarz@wp.pl>: Aug 14 03:03PM +0200 W dniu 14.08.2020 o 14:43, Sam pisze: >> How to correct my code? > Get rid of new and delete, complete. Use vectors, or lists, or some > other container that will do this for you. I tried heap allocation because I had core dumped when I used stack allocation (local variables). I don't know why because I use little memeory. |
RM <robert_magdziarz@wp.pl>: Aug 14 03:46PM +0200 > I tried heap allocation because I had core dumped when I used stack > allocation (local variables). I don't know why because I use little > memeory. I use g++ in Linux Mint. |
RM <robert_magdziarz@wp.pl>: Aug 14 03:55PM +0200 W dniu 14.08.2020 o 15:46, RM pisze: >> allocation (local variables). I don't know why because I use little >> memeory. > I use g++ in Linux Mint. To be precise I have core dumped and I have in gdb: #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 51 ../sysdeps/unix/sysv/linux/raise.c: Nie ma takiego pliku ani katalogu. (gdb) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 #1 0x00007f98bd7d5801 in __GI_abort () at abort.c:79 #2 0x00007f98bde2a957 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #3 0x00007f98bde30ae6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #4 0x00007f98bde30b21 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #5 0x00007f98bde30d54 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #6 0x00007f98bde312dc in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #7 0x00007f98bdec2b8b in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #8 0x00007f98bdec4133 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #9 0x00000000004098d1 in std::operator+<char, std::char_traits<char>, std::allocator<char> > (__lhs=..., __rhs="") at /usr/include/c++/7/bits/basic_string.h:5955 #10 0x000000000040838e in obfuscator::obfuscator (this=0x7ffd4feca0e0) at src/obfuscator.hpp:69 #11 0x000000000040781b in main (argc=6, argv=0x7ffd4feca678) at src/dirtyphp.cpp:37 |
RM <robert_magdziarz@wp.pl>: Aug 14 04:16PM +0200 W dniu 14.08.2020 o 15:55, RM pisze: > at src/obfuscator.hpp:69 > #11 0x000000000040781b in main (argc=6, argv=0x7ffd4feca678) > at src/dirtyphp.cpp:37 After reinstalling g++ I have: #0 __memmove_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:371 371 ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: Nie ma takiego pliku ani katalogu. (gdb) bt #0 __memmove_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:371 #1 0x00007fa7a3e55bda in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #2 0x00007fa7a3e57133 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_append(char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 #3 0x00000000004098d1 in std::operator+<char, std::char_traits<char>, std::allocator<char> > (__lhs=..., __rhs="\020(\v\244\247\177\000\000\002\000\000\000\000\000\000\000H\374\n\244\247\177\000\000\002\000\000\000\000\000\000\000\000t\v\244\247\177\000\000\000\000\000\000\000\000\000\000\330\373\n\244\247\177\000\000\002\000\000\000\000\000\000\000`)\261\243\247\177", '\000' <repeats 26 times>, "\020\330\n\244\247\177\000\000\002\000\000\000\000\000\000\000`)\261\243\247\177\000\000\001\000\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMN"...) at /usr/include/c++/7/bits/basic_string.h:5955 #4 0x000000000040838e in obfuscator::obfuscator (this=0x7ffe10828cb0) at src/obfuscator.hpp:69 #5 0x000000000040781b in main (argc=6, argv=0x7ffe10829248) at src/dirtyphp.cpp:37 |
Barry Schwarz <schwarzb@delq.com>: Aug 14 07:47AM -0700 >src/obfuscator.hpp:75:51: error: incompatible types in assignment of >'strvector*' to 'strvector [5]' > identifiers = new strvector[INDEX_WHAT_NUM]; This error message is inconsistent with the above code. identifiers does not have type strvector[5]. It has type strvector(*)[5] which is completely different. The easiest way for us to help you would be for you to provide a small, complete, compilable program that produces the error in question. When you post the program in a message, use cut and paste rather than retype it. Retyping often introduces mistakes that don't appear in the original. In a subsequent message you stated you had problems using arrays that were declared explicitly. Show us that code also so we can see what you are doing wrong. Based on both messages, I think you have a fundamental misunderstanding about arrays but we will probably be able to correct that also when you show us the code. -- Remove del for email |
Bo Persson <bo@bo-persson.se>: Aug 14 06:32PM +0200 On 2020-08-14 at 14:16, RM wrote: > 'strvector*' to 'strvector [5]' > framework_identifiers = new strvector[INDEX_WHAT_NUM]; > How to correct my code? You have to consider if you want an array of pointers, strvector (*identifiers)[INDEX_WHAT_NUM] or a pointer to an array new strvector[INDEX_WHAT_NUM] Those are not the same thing. BTW, a std::vector doesn't store the data elements on the stack, but uses heap allocation internally (and likely does that correctly :-)). If you run out of stack space, you have some other problem. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 14 07:06PM +0200 On 14.08.2020 14:16, RM wrote: > [snip] > strvector (*identifiers)[INDEX_WHAT_NUM], This is a pointer to a complete array of `strvector`, because `*identifiers` gives you what identifiers points to, and THAT[n] gives you the beyond-the-last item. Instead of using the old C syntax you could write std::array<strvector, INDEX_WHAT_NUM>* identifiers; Or instead of using the standard library type you could define template< class T > using Type_ = T; and then write Type_<strvector[INDEX_WHAT_NUM]>* identifiers; The question is whether that's what you really wanted, because > [snip] > identifiers = new strvector[INDEX_WHAT_NUM]; ... produces a `strvector*, i.e. a pointer to the first item in the allocated array, and not a pointer to the complete array as such. The difference is just one of type, not of memory address. But it's enough to make the compiler say no. [snip] > How to correct my code? It depends what you want. If you just want a dynamic size array of strings, then vector<string> m_identifiers; But if you want a dynamic size array of dynamic size arrays of strings, then vector<vector<string>> m_identifiers; That's closest to the presented code but I believe you really want the first one. - Alf |
Juha Nieminen <nospam@thanks.invalid>: Aug 14 05:26PM > strvector (*identifiers)[INDEX_WHAT_NUM], > (*random_identifiers)[INDEX_WHAT_NUM], > (*framework_identifiers)[INDEX_WHAT_NUM]; The answers to this question go to show that even many experienced C++ programmers don't know their pointer syntax. Type (*name)[size] is a pointer to a Type[size], ie. an array of size elements of type Type. This is *not* the same thing as a pointer-to-Type. This is a pointer-to-Type[size], which is different. For instance, if you increment a Type*, it will advance by sizeof(Type) bytes, but if you increment a Type(*)[size], it will advance by sizeof(Type)*size bytes. Most often Type(*name)[size] is used as a pointer to a 2-dimensional array, where the second dimension is 'size'. In other words: Type table[12][34]; Type (*ptr)[34] = table; Here you see that if you do a ++ptr, it will advance to the next row in the array, ie. it will advance by an entire row, ie by sizeof(Type)*34 bytes. Your code does not look like you want a pointer to a 2-dimensional array. It looks to me that you simply wanted: strvector *identifiers, *random_identifiers, *framework_identifiers; These are pointers-to-strvector, which also double as "pointer to an array of strvector objects" (an ambiguity inherited from C). That being said, it's usually recommended against using raw pointers and 'new'. Just use members of strvector directly: strvector identifiers, random_identifiers, framework_identifiers; Since strvector is just an std::vector, there's really no reason not to. |
Barry Schwarz <schwarzb@delq.com>: Aug 14 11:16AM -0700 On Fri, 14 Aug 2020 18:32:02 +0200, Bo Persson <bo@bo-persson.se> wrote: >You have to consider if you want an array of pointers, >strvector (*identifiers)[INDEX_WHAT_NUM] That is not an array of pointers. It is a pointer to an (entire) array. An array of pointers would be declared as strvector *array[5] -- Remove del for email |
Sam <sam@email-scan.com>: Aug 14 05:51PM -0400 RM writes: >> container that will do this for you. > I tried heap allocation because I had core dumped when I used stack > allocation (local variables). I don't know why because I use little memeory. If you do not understand the reason why your program crashes, trying different things at random will rarely fix anything. Especially other things that you don't even fully understand the inner workings of. You need to investigate the reason for your crashes, and fix them. Unfortunately, posting your backtraces to the Intertubes does not convey anything meaningful. Backtraces are utterly useless to anyone except the one who produced the backtrace. Backtraces aren't, by themselves a "here's where the bug is" solution. All that a backtrace tells you is the sequence of function calls that led to the crash. How does that tell you what the bug is? Very rarely it does, but almost never. Backtraces are only a starting point. Unfortunately there is no paint-by- numbers, cookie-cutter recipe for figuring out the bug, from a backtrace. Each crash is unique, and distinct in its nature. Typically one would see, from the backtrace, where your written code ends, and system libraries start (if any), then go up to call stack back to where your code made the library call, then investigate the state of the program and the data, at the time of the library call. Inspect all variables, pointers, determine what the problem with the state of the program is. Maybe even back up a few more stack frames, if it's clear that something went sideways further up the call chain. Or, you may discover such a dumpster fire already in progress that the only thing that you can do is set a breakpoint earlier in the code, at some meaningful place, before execution reaches here, run the program again, and see how things shape up at an earlier point in the execution. |
Juha Nieminen <nospam@thanks.invalid>: Aug 14 12:14AM > when you don't realize you have *this* problem. > If you don't have use for co-routines this does not mean nobody does. > For example, I have not found use for std::list and I'm not complaining. It took me some time to understand what coroutines are good for, but once I figured out this practical example, I think it' makes it quite clear. (I have mentioned this in the past, but I suppose it doesn't hurt repeating.) Suppose you are decompressing a file (or compressed data that's coming in or whatever). You have a fixed-sized array into which you are storing the decompressed data. The idea is that once the array gets full, you should call some "consumer" code that handles the uncompressed data (and thus "empties" the array of it), after which you continue decompressing more data into it. The thing is, compressed data tends to be in some kind of chunks, ie. when you decompress one "unit" if compressed data, the resulting decompressed data may not fit neatly in the array, filling it completely (or fitting inside it in the first place, even if the array was empty). You would need to partially decompress this chunk of compressed data and fill the array with the decompressed data, call the "consumer" code, and then continue decompressing from where you left (now filling the array from the beginning). In other words, you need to be able to stop decompressing somewhere in the middle of your decompression routine, call the outside code, and then resume from where you left. Normally this means that you need to store the entire state of your decompressor somewhere, and then code the logic that allows you to continue from where you left off. This becomes quite complicated if there are many points in the decompressor code where the output array may get full and thus it needs to stop, call the "consumer", and then continue. This is where coroutines step in to largely automatize this entire process. At any point in your decompressor, if the output array may get full, you simply "yield", and then continue as normal. You don't need to keep the entire decompressor state stored somewhere, you don't need to remember which "yield" point you were last in, you don't need to code any logic to jump back to that particular "yield" point. Coroutines take care of all that automatically for you. It is, of course, perfectly possible to do all this without coroutines, but it's much more laborious. Coroutines automatize most of this. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 14 06:52AM +0200 On 14.08.2020 02:14, Juha Nieminen wrote: > It is, of course, perfectly possible to do all this without > coroutines, but it's much more laborious. Coroutines automatize > most of this. It used to be called a Jackson (data) "structure clash" problem. Not after Michael Jackson, but after the Jackson who invented manually structured Cobol programming. I remember that some years ago it was already very difficult to convince Mr. Google to find anything about it, but at one time just about every corporate developer knew about it. - Alf |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 14 07:10AM On Thu, 2020-08-13, Brian Wood wrote: > Years ago Gcc and Clang were making some progress on > static exceptions. I'm wondering if that work has been > totally derailed now by 2020 C++. I don't know anything about the feature, but it's normal for a new language feature to get prototyped in either of those compilers. Then people play with it, and if enough like it, it ends up in the language. Compiler-specific extensions haven't been popular in recent decades, so if it turns out the feature won't be standardized, it probably won't make it to a real g++ or clang release. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
Sam <sam@email-scan.com>: Aug 14 07:11AM -0400 Paavo Helde writes: >> problem. > More like a solution which you need to poorly reinvent or work around when > you don't realize you have *this* problem. I have no idea where I would be without someone telling me that I have some problem I don't know about. Probably sitting in a dark room, pulling my hair out, or something, living in perpetual fear of all these hidden problem boogeymen. |
Sam <sam@email-scan.com>: Aug 14 07:15AM -0400 Juha Nieminen writes: > clear. (I have mentioned this in the past, but I suppose it doesn't > hurt repeating.) > Suppose you are decompressing a file (or compressed data that's Or, instead of doing all of this, implement a push-based API. > It is, of course, perfectly possible to do all this without > coroutines, but it's much more laborious. Coroutines automatize > most of this. Gee, that's neat. Almost as neat as throw specifications. Oh, wait… |
Juha Nieminen <nospam@thanks.invalid>: Aug 14 05:14PM >> coroutines, but it's much more laborious. Coroutines automatize >> most of this. > Gee, that's neat. Almost as neat as throw specifications. Oh, wait??? Sounds more like the stubborn people who complain about all changes will refuse to use it, while people who understand the use of the feature will save themselves a lot of trouble by just using it. It's like those C hackers who always complain how templates are too complicated and how they love to make everything by hand in C, while experienced C++ programmers will just use templates without much problems and get things done much easier and faster (and often even producing a more efficient result). |
red floyd <no.spam.here@its.invalid>: Aug 14 01:36PM -0700 On 8/14/2020 4:11 AM, Sam wrote: > some problem I don't know about. > Probably sitting in a dark room, pulling my hair out, or something, > living in perpetual fear of all these hidden problem boogeymen. So if you don't have a need for the feature, don't use it. Just because it doesn't fit YOUR use case, doesn't mean that others don't like it. Chill out, dude. |
Sam <sam@email-scan.com>: Aug 14 05:50PM -0400 Juha Nieminen writes: > Sounds more like the stubborn people who complain about all changes will > refuse to use it, while people who understand the use of the feature > will save themselves a lot of trouble by just using it. I wonder how many people decided that throw specifications were the greatest thing since sliced bread, and started sprinkling them all over the place, as a prophylactic measure, to catch bugs earlier? Where are they now? Or, everyone who thought that std::vector<bool> was brilliant. Very useful, right? |
Sam <sam@email-scan.com>: Aug 14 05:50PM -0400 red floyd writes: > > living in perpetual fear of all these hidden problem boogeymen. > So if you don't have a need for the feature, don't use it. Just because > it doesn't fit YOUR use case, doesn't mean that others don't like it. Where did I claim that nobody liked it? I never said that. The only thing that I said is that it's something I would've come up with myself, after injesting a few mushrooms. I'm sure that someone, some time ago, really liked `std::vector<bool>`, and thought that it was the greatest invention that humankind ever made. I'm sure that there will be those that, for whatever reasons, like co- routines, and start cranking them out like they're going out of style. Bless their little hearts. I really don't understand why someone would get so disjointed in response to my disparaging remarks. I'm humbled at the thought that someone values my opinions so much that they get enturbulated when I dis their favorite toys. If someone started bad-mouthing, for example, real execution threads – which is something that I'm very found of – I don't think I'd care. I'd read the rant, smirk, and move on. Why would I care about some other rando's stream of consciousness? Who are they to me? Nobody. Why should I care? Can't think of a reason. > Chill out, dude. I'm perfectly chilled. |
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