- c++ 20 - 17 Updates
- GNU compiler g++ most extreme debugging - 8 Updates
| Muttley@dastardlyhq.com: Jun 23 07:11AM On Wed, 22 Jun 2022 19:05:54 +0200 >No, it creates a new vector with these values. That's initialization, >like in setting its initial value. >Assignment is when there already is an objects, and it gets a new value. Initialisation is the whole process, assignment is specifically setting the values and the terminology doesn't depend on whether a value is already there. Like I said, you're splitting hairs but call it whatever you want, I'm not getting into another idiotic language argument with someone for whom english is a 2nd language anyway. |
| Muttley@dastardlyhq.com: Jun 23 07:16AM On Wed, 22 Jun 2022 19:16:02 +0200 >differences between initialisation and assignment, and if you want to >understand the language you should make a point of learning about these >differences. Ah, we're in to patronising territory already which is usually an indication that the poster is backing into a corner. >incorrect terms, that's your choice - it will be good enough for simple >coding. But it would be nice if you didn't try to confuse learners by >using inaccurate terms. I'm using the standard english terms, I'm not interested in how its described in some dusty corner of the spec. And FWIW I doubt there are any learners on here. How you describe something has zero effect on code unless you believe in psychokinesis. Perhaps you do. Just in case you're still confused: https://www.oxfordlearnersdictionaries.com/definition/english/assign "to say that something has a particular value or function, or happens at a particular time or place" Eg at vector initialisation time. HTH. |
| Christian Gollwitzer <auriocus@gmx.de>: Jun 23 09:12AM +0100 > I'm using the standard english terms, I'm not interested in how its described > in some dusty corner of the spec. But you are talking to people who use them in their standard defined meaning. You missed that words have multiple meanings, and especially in science and technology these meanings sometime differ from the general usage. E.g. a "theory" in colloquial English is a vague idea for an explanation, what scientists call a "hypothesis", while a "theory" in science is a model backed up by and generalising all available evidence. Likewise, "assignment" and "initialisation" are technical terms for C++ programmers, and when you call them "wurzlbrmpft" and "kohlrabi" you would just induce confusion among the people who use them in their defined meaning, and even more when you mix them up. Christian |
| David Brown <david.brown@hesbynett.no>: Jun 23 11:33AM +0200 >> Assignment is when there already is an objects, and it gets a new value. > Initialisation is the whole process, assignment is specifically setting the > values and the terminology doesn't depend on whether a value is already there. Bo is correct. Words like "initialisation" and "assignment" have specific meanings in the language, and it is useful to get in the habit of using them accurately. You are right that assignment can happen without a value being in the object ("int x; x = 1;"). But the object has to exist and have completed its initialisation, if any, before an assignment can happen. > Like I said, you're splitting hairs but call it whatever you want, It is what the standards call it, not necessarily what any C++ user wants. (Most C++ users would want the whole thing simplified a bit.) > I'm not > getting into another idiotic language argument with someone for whom english is > a 2nd language anyway. Bo's English is at least as good as yours. |
| David Brown <david.brown@hesbynett.no>: Jun 23 11:37AM +0200 >> using inaccurate terms. > I'm using the standard english terms, I'm not interested in how its described > in some dusty corner of the spec. This is not a "dusty corner" of the language specification - it's an important concept in C++. The distinction between initialisation and assignment is not an easy matter, and you can reasonably argue that it is more complicated that it really should be. But you have to learn it, and you should try to use the terms accurately. It makes no practical difference for simple object types, such as "int" here, but it /does/ make a difference with more complicated code. > "to say that something has a particular value or function, or happens at a > particular time or place" > Eg at vector initialisation time. Why would you think a dictionary entry is of relevance to technical terms with specific meanings in a programming language standard? |
| Juha Nieminen <nospam@thanks.invalid>: Jun 23 11:07AM >>differences. > Ah, we're in to patronising territory already which is usually an indication > that the poster is backing into a corner. There's nothing patronizing about that response. It's simply stating an important fact about C++. >>using inaccurate terms. > I'm using the standard english terms, I'm not interested in how its described > in some dusty corner of the spec. You should not be using "standard english terms" when it comes to such things in C++ because if you do so you'll be causing confusion and even misunderstandings. "Initialization" and "assignment" have very specific meanings in C++ and can't be used interchangeably. One quite prominent way of seeing the difference is that for custom types assignment can be disabled (you'll get a compiler error if you try) while initialization is enabled. (The other way around is possible too.) There are, in fact, some utility classes in the standard library where that's exactly the case, most prominently std::unique_ptr. You can initialize it but you can't (copy) assign one. (You can move assign, but that's a bit different.) |
| Juha Nieminen <nospam@thanks.invalid>: Jun 23 11:13AM >> demarcation (though IMO [] would have made more sense) but is silly for a >> simple assignment. > The point is exactly that it isn't an assignment. It is an initialization. And, in fact, they are two rather different types of initialization: The first one is calling a constructor taking an int, while the second one is calling a copy constructor (although the compiler is optimize that construction-the- temporary-and-calling-the-copy-constructor away and just call the regular constructor with the given value). I have seen some people even use this idiom, with no understanding of that difference: auto vec = std::vector { 1, 2, 3, 4 }; While normally the compiler is allowed to optimize the temporary and the copy constructor call away, I'm actually not sure it can do that in this case. I find this idiom abhorrent. |
| Muttley@dastardlyhq.com: Jun 23 01:16PM On Thu, 23 Jun 2022 09:12:45 +0100 >> I'm using the standard english terms, I'm not interested in how its described >> in some dusty corner of the spec. >But you are talking to people who use them in their standard defined Yes I know the autism level is high on here. |
| Muttley@dastardlyhq.com: Jun 23 01:20PM On Thu, 23 Jun 2022 11:33:22 +0200 >without a value being in the object ("int x; x = 1;"). But the object >has to exist and have completed its initialisation, if any, before an >assignment can happen. Exactly. Initialisation consists of allocating the memory. Then you ASSIGN the values to that memory. >is >> a 2nd language anyway. >Bo's English is at least as good as yours. Highly unlikely. |
| Muttley@dastardlyhq.com: Jun 23 01:22PM On Thu, 23 Jun 2022 11:37:57 +0200 >> Eg at vector initialisation time. >Why would you think a dictionary entry is of relevance to technical >terms with specific meanings in a programming language standard? Because spoken languages are defined in dictionaries, not in computer progamming manuals. Memory gets assigned a value. |
| Muttley@dastardlyhq.com: Jun 23 01:23PM On Thu, 23 Jun 2022 11:07:49 -0000 (UTC) >that's exactly the case, most prominently std::unique_ptr. You can >initialize it but you can't (copy) assign one. (You can move assign, but >that's a bit different.) I don't see your point. You're still assigning a value to it, the fact that you can only do it the once is neither here nor there. |
| David Brown <david.brown@hesbynett.no>: Jun 23 04:10PM +0200 >> assignment can happen. > Exactly. Initialisation consists of allocating the memory. Then you ASSIGN > the values to that memory. That is not correct usage of the technical terms (and it is the technical terms that matter). Initialisation does not consist solely of allocating memory, nor is allocation of memory necessary for many initialisations. >>> a 2nd language anyway. >> Bo's English is at least as good as yours. > Highly unlikely. I've noticed a fair number of grammatical errors in your writing, but none in Bo's posts. Of course I have not examined all his posts. My experience with well-educated Scandinavians (and I am confident I have more experience with them than you) is that their written English is frequently more accurate than native English speakers. They sometimes have tell-tail habits in their spoken English, and they won't use the same range of idioms. Certainly any argument on the basis of Bo's mastery of English as a second language is unjustified. |
| Juha Nieminen <nospam@thanks.invalid>: Jun 23 02:56PM >>that's a bit different.) > I don't see your point. You're still assigning a value to it, the fact that > you can only do it the once is neither here nor there. Seriously, how hard it is to just say "ah, sorry, my bad, I stand corrected. I learned something new today", instead of just going into this endless and futile quest of trying to "win" and to "be right" in such a petty little thing? Admitting not having known something, or having made a small mistake, is not a bad thing, nor is it shameful. You don't have to always "win". You don't have to always "be right". You can perfectly well be mistaken, admit it, learn from the mistake, and nobody will ridicule you. The longer you continue this silly quest of yours of trying to defend your mistake as not being a mistake, the deeper you will be digging that hole where you wouldn't even have to be. In other words, and rather ironically, you are shaming yourself by trying so desperately to be right, rather than admitting that you didn't know (or were mistaken). This is really not a hill to die on. Just say "I stand corrected" and move on. Nobody will blame you for that. (Now expecting your "I didn't read any of that" with an assortment of insults response...) |
| Muttley@dastardlyhq.com: Jun 23 03:14PM On Thu, 23 Jun 2022 16:10:27 +0200 >technical terms that matter). Initialisation does not consist solely of >allocating memory, nor is allocation of memory necessary for many >initialisations. So the value doesn't get assigned to the memory. It just magically appears there? >> Highly unlikely. >I've noticed a fair number of grammatical errors in your writing, but >none in Bo's posts. Of course I have not examined all his posts. My I write my posts in vi without any spell checking plugins and given I'm working I have better things to do that double check spellings to keep pedants like you happy. |
| Muttley@dastardlyhq.com: Jun 23 03:19PM On Thu, 23 Jun 2022 14:56:27 -0000 (UTC) >I learned something new today", instead of just going into this endless and >futile quest of trying to "win" and to "be right" in such a petty little >thing? Its not me arguing the toss or making a big deal out of it. Computer memory has values assigned to it whereas initialisation is what happens at power on. End. Just because C++ uses a different definition doesn't change that fact nor does it make my original post wrong. >a bad thing, nor is it shameful. You don't have to always "win". You don't >have to always "be right". You can perfectly well be mistaken, admit it, >learn from the mistake, and nobody will ridicule you. Oh bless, you're so kind. |
| Christian Gollwitzer <auriocus@gmx.de>: Jun 23 05:29PM +0200 >> initialisations. > So the value doesn't get assigned to the memory. It just magically appears > there? Believe it or not, in some cases that is exactly what's happening. For example, if you have a static file scope variable static int x = 42; int somefunc() { } then this might be translated into a section of the executable which contains the static variables. Therefore, upon starting the program, the values 42 will just "magically" be there (it comes with the code). There is no explicut "MOV"-instructino or the like. Of course, these things go beyond the C++ standard, and you should not worry about them. The compiler will do the right thing for you. Christian |
| Muttley@dastardlyhq.com: Jun 23 03:37PM On Thu, 23 Jun 2022 17:29:18 +0200 >then this might be translated into a section of the executable which >contains the static variables. Therefore, upon starting the program, the >values 42 will just "magically" be there (it comes with the code). There Yes, thats right, its all magic. >is no explicut "MOV"-instructino or the like. Nooooooo! Really?? Incredible! |
| Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 04:46AM -0700 A week ago here in comp.lang.c++ I started a thread entitled "Can any tool catch this invalid memory access?". One or two people said I should use valgrind, but valgrind is useless at detecting invalid access to static data or stack data. Valgrind is only effective at detecting invalid access to the heap. Then I tried using g++ with the command line option "-fsanitize", and it works very well, it successfully flagged invalid access to an array on the stack. Just today I tried "-D_GLIBCXX_DEBUG", and I'm actually a little mesmerized at how effective it is. It catches *everything*, especially invalid access to STL containers and also classes such as string_view. So right now here's how I'm building my program: g++ -o precompiler precompiler.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all This is working very well for me, but if anyone has any more suggestions for even more extreme debugging, I'm all ears. |
| David Brown <david.brown@hesbynett.no>: Jun 23 02:18PM +0200 On 23/06/2022 13:46, Frederick Virchanza Gotham wrote: > So right now here's how I'm building my program: > g++ -o precompiler precompiler.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all > This is working very well for me, but if anyone has any more suggestions for even more extreme debugging, I'm all ears. Some problems can only be caught at run time, and you've got a good selection of flags and tools for that. But it is even better to catch problems at compile time. Make good use of the compiler's static warning facilities. At a minimum, enable "-Wall" and optimisation of at least "-O1". (With no optimisation, less code analysis is done and fewer errors are spotted.) You should also try "-Wextra", though some of the flags enabled there are controversial. <https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html> The new gcc "static analyzer" may also be helpful, depending on your code : <https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html> |
| Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 06:44AM -0700 On Thursday, June 23, 2022 at 12:46:34 PM UTC+1, I wrote: > This is working very well for me, but if anyone has any more suggestions for even more extreme debugging, I'm all ears. I'm still trying to find a debugger that will flag the error in the following code. I've written a function called "Increment_First_And_Print_Without_First" which takes an input such as the word "brush", and it prints out: rush crush Inside the body of "Increment_First_And_Print_Without_First", I dereference an iterator to one-past-the-last, which is undefined behaviour. Here's how I build the following program: g++ -o iterator_deref iterator_deref.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all When I run the program, no error is flagged. No error is flagged in 'gdb' either. I haven't found any debugging tool that can find this error. Here's the code: #include <iostream> #include <string> #include <string_view> #include <type_traits> using namespace std; void Increment_First_And_Print_Without_First(string &s) { if ( s.size() < 2u ) throw -1; ++( s[0u] ); // The next line has an invalid dereferencing of an iterator cout << "The next line dereferences an end() pointer" << endl; cout << string_view( &*(s.cbegin() + 1u), &*(s.cend()) ) << endl; } int main(void) { cout << "string::const_iterator is " << (is_same_v< string::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl; cout << "string_view::const_iterator is " << (is_same_v< string_view::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl; string str("brush"); Increment_First_And_Print_Without_First(str); cout << str << endl; } On my x86_64 Ubuntu PC here, the output I get is: string::const_iterator is NOT a simple pointer string_view::const_iterator is just a raw pointer The next line dereferences an end() pointer rush crush |
| Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 07:01AM -0700 On Thursday, June 23, 2022 at 2:44:44 PM UTC+1, Frederick Virchanza Gotham wrote: > When I run the program, no error is flagged. No error is flagged in 'gdb' either. I haven't found any debugging tool that can find this error. Actually here's a smaller simpler program: #include <iostream> #include <string> #include <string_view> #include <type_traits> using namespace std; int main(void) { cout << "string::const_iterator is " << (is_same_v< string::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl; cout << "string_view::const_iterator is " << (is_same_v< string_view::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl; string s("brush"); cout << string_view( &*(s.cbegin() + 1u), &*(s.cend() + 876u) ) << endl; } On my x86_64 Ubuntu Linux PC, this prints garbage but doesn't crash. I was hoping "-fsanitize" would catch the "+876" on the last line. |
| David Brown <david.brown@hesbynett.no>: Jun 23 04:03PM +0200 On 23/06/2022 15:44, Frederick Virchanza Gotham wrote: > Inside the body of "Increment_First_And_Print_Without_First", I dereference an iterator to one-past-the-last, which is undefined behaviour. Here's how I build the following program: > g++ -o iterator_deref iterator_deref.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all > When I run the program, no error is flagged. No error is flagged in 'gdb' either. I haven't found any debugging tool that can find this error. You are dereferencing the iterator, then taking its address. In C, "&*x" is treated exactly as "x" except for constraint checking and making the result an lvalue. So it is defined behaviour, even if "x" were a null pointer. I don't see anything matching that (section 6.5.3.2p3) in the C++ standards. But it is possible that the "&*" pair gets removed early in the compilation process, and is not seen by any of the sanitizers or checkers. After all, you are not really dereferencing the iterator - you are taking the address of the dereference. |
| Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 07:47AM -0700 On Thursday, June 23, 2022 at 3:03:31 PM UTC+1, David Brown wrote: > You are dereferencing the iterator, then taking its address. The expression, "s.cend()", is of type string::const_iterator, which is not a simple pointer (or at least it's not a simple pointer on my g++ compiler). > In C, "&*x" is treated exactly as "x" except for constraint checking and > making the result an lvalue. I think you mean R-value. I'm only concerned with C++ right now. Is there anything in the C++ standard that says you can dereference an invalid pointer so long as you immediately take the address of the pointed-to thing? Is the following program valid in C++20? int main(void) { char *p = nullptr; &*p; } By the way "&*" has an observable effect when used on an array, for example: Define an array: char buf[64]; The expression "buf" is an L-value of type "char[64]" The expression "&*buf" is an R-value of type "char*" > gets removed early in the compilation process, and is not seen by any of > the sanitizers or checkers. After all, you are not really dereferencing > the iterator Yes I am dereferencing the iterator. No doubt about it -- the iterator is getting dereferenced. > you are taking the address of the dereference. This also happens. |
| Juha Nieminen <nospam@thanks.invalid>: Jun 23 03:04PM > One or two people said I should use valgrind, but valgrind is useless at detecting invalid access to static data or stack data. Valgrind is only effective at detecting invalid access to the heap. While calling valgrind "useless" is technically correct in this context, to catch this kind of mistake, I think it's quite a strong word with quite a negative connotation, which I feel is a bit unfair towards the program. The program itself is great for debugging the things that it does support. It can't catch (most) out-of-bounds accesses on the stack because that's quite literally impossible (without the help of the compiler), but you merely need to be aware of that. I think it would be nicer to just say that "valgrind can't detect these types of error", and not dismiss its usefulness in the things it has actually been designed to test (ie. heap allocations and accesses). > Just today I tried "-D_GLIBCXX_DEBUG", and I'm actually a little mesmerized at how effective it is. It catches *everything*, especially invalid access to STL containers and also classes such as string_view. To be more precise, it catches (most) wrong uses of the standard library. (That's what the "GLIBCXX" is referring to. It's a macro used in the standard library implementation used by gcc.) It won't catch errors that are not related to the standard library utilities. |
| Juha Nieminen <nospam@thanks.invalid>: Jun 23 03:07PM > cout << string_view( &*(s.cbegin() + 1u), &*(s.cend() + 876u) ) << endl; > } > On my x86_64 Ubuntu Linux PC, this prints garbage but doesn't crash. I was hoping "-fsanitize" would catch the "+876" on the last line. Have you tried to run the program through valgrind? Because it has been designed precisely for that (you are accessing dynamically allocated memory out of bounds). |
| 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