- What was the reasoning behind &'s syntax? - 19 Updates
- Are concepts like interfaces for templates? - 5 Updates
- My C++ synchronization objects library was extended.. - 1 Update
Jerry Stuckle <jstucklex@attglobal.net>: May 07 07:52PM -0400 On 5/3/2016 2:44 PM, Rick C. Hodgin wrote: > reference or not without additional interrogation of the source code. > Best regards, > Rick C. Hodgin That is an incorrect statement. For instance: #include <iostream> void callByRef(int & cr) { std::cout << "The address of cr is " << &cr << std::endl; return; } int main (void) { int *pi = NULL; int &ri = *pi; callByRef(ri); return 0; } Output: The address of cr is 0 -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 07 05:20PM -0700 On Saturday, May 7, 2016 at 7:52:34 PM UTC-4, Jerry Stuckle wrote: > } > Output: > The address of cr is 0 Well of course. We're back to the pointer issue. Anytime pointers are involved you need to check the pointer before you use it. If you use references with real values, or pointer values where the pointer has already been validated, then you don't need to check when the associated reference is used. int main (int argc, char* argv[]) { int *pi = NULL; if (pi) { // We're good int &ri = *pi; callByRef(ri); return 0; } else { // Invalid pointer std::cout << "NULL pointer" << std::endl; return -1; } } Best regards, Rick C. Hodgin |
Jerry Stuckle <jstucklex@attglobal.net>: May 07 09:21PM -0400 On 5/7/2016 8:20 PM, Rick C. Hodgin wrote: > } > Best regards, > Rick C. Hodgin But you said it was impossible to have a reference to NULL. I just pointed out that is NOT the fact. So your argument is false. The function has no idea what was passed to it. Unlike a copy (which is always allocated on the stack), a reference *can* point at NULL - just like a pointer. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 07 07:00PM -0700 On Saturday, May 7, 2016 at 9:22:02 PM UTC-4, Jerry Stuckle wrote: > > Rick C. Hodgin > But you said it was impossible to have a reference to NULL. I just > pointed out that is NOT the fact. So your argument is false. What I said was: "[References] remove the need to check for NULL because all reference params come in guaranteed by the compiler to be non-NULL. The only way they can be non-NULL is if some illegal and sneaky or tricky [thing] happens." > The function has no idea what was passed to it. Unlike a copy (which is > always allocated on the stack), a reference *can* point at NULL - just > like a pointer. There's protocol, Jerry. People can always weasel and snake their way around and force things that ultimately cause much harm. And as I say, whenever you work with pointers you must check them. Doing so in your contrived example would've prevented the issue. It wasn't a failure on the reference side, or in the compiler, but in the way the reference was used without first checking the pointer. ----- You did bring up a point that I was surprised to see in a C++ compiler, by the way. When you used "int &ri = *pi;" I was surprised the compiler allowed the runtime de-reference on a NULL to be stored in a reference. While I recognize it's just using the address that's in use, I would've thought the compiler would at least do a runtime check on the pointer and in that way generate the error there where the NULL pointer is being de-referenced. I also think the C++ compiler _should_ do that. Doing so would've caught bugs like this one in your example. Best regards, Rick C. Hodgin |
Jerry Stuckle <jstucklex@attglobal.net>: May 07 11:08PM -0400 On 5/7/2016 10:00 PM, Rick C. Hodgin wrote: > all reference params come in guaranteed by the compiler to be non-NULL. > The only way they can be non-NULL is if some illegal and sneaky or tricky > [thing] happens." And I proved you wrong. There is nothing illegal in my code, nor is there a sneaky trick. It's just a very simplified example of what can easily happen, and the reference param is NULL. I could have done something fancier - like set up a linked list and pass a reference to a list element. But one past the end of the list would have been a reference to NULL. I just tried to keep it simple enough for anyone to understand. >> like a pointer. > There's protocol, Jerry. People can always weasel and snake their way > around and force things that ultimately cause much harm. No "weasel and snake their way", Rick. Something which can easily happen. > so in your contrived example would've prevented the issue. It wasn't a > failure on the reference side, or in the compiler, but in the way the > reference was used without first checking the pointer. But that doesn't always happen. And yes, it is a contrived example. I wanted to ensure it was simple enough for anyone to understand. But it shows your statement is false. > like this one in your example. > Best regards, > Rick C. Hodgin The compiler never checks pointers. As with C, it is the programmer's responsibility to ensure the pointers contain valid addresses. C++ doesn't hold your hand any more than C does. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 07 08:28PM -0700 On Saturday, May 7, 2016 at 11:08:30 PM UTC-4, Jerry Stuckle wrote: > > [thing] happens." > And I proved you wrong. There is nothing illegal in my code, nor is > there a sneaky trick. You're de-referencing a NULL pointer, which is illegal. The fact that the compiler did not catch it at runtime highlights a flaw in the compiler and or C++ standard, because the error you created should never have been allowed to occur. > The compiler never checks pointers. As with C, it is the programmer's > responsibility to ensure the pointers contain valid addresses. C++ > doesn't hold your hand any more than C does. I believe the C++ compiler should in this case. When you're de-referencing a pointer that will then be passed as a reference, the compiler should inject code to perform the NULL check right there, to catch the error at its cause, just as if the code had been used as "int i = *pi;" would've done. Best regards, Rick C. Hodgin |
Rosario19 <Ros@invalid.invalid>: May 08 05:39AM +0200 On Sat, 7 May 2016 20:28:09 -0700 (PDT), "Rick C. Hodgin" wrote: >I believe the C++ compiler should in this case. When you're de-referencing >a pointer that will then be passed as a reference, the compiler should inject >code to perform the NULL check right there, to catch the error at its cause, so each time de-reference it has to check if it is NULL? no... the time only when the pointer change value if it is used as adrress with * but when do you sleep? |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 07 08:54PM -0700 On Saturday, May 7, 2016 at 11:39:28 PM UTC-4, Rosario19 wrote: > >a pointer that will then be passed as a reference, the compiler should inject > >code to perform the NULL check right there, to catch the error at its cause, > so each time de-reference it has to check if it is NULL? It won't actually check if it's NULL as by injecting a test, but it will try to read from the de-referenced location, which would signal the error just as it would've had it been used in an "int i = *pi;" version. > no... the time only when the pointer change > value if it is used as adrress with * That's the way the compiler works today, and Jerry's code failed to check for a NULL pointer, and therefore the bug came through. I don't think it should be that way. Whenever you're passing the result of a pointer's value as a by-reference value, it should test the value before arbitrarily sending the value. It will be a minor performance hit, but negligible for the extra safety it provides. You could, of course, also bypass the performance hit by assigning it only one time, and from that point forward passing the reference. It would remain valid so long as the pointer remains valid. > but when do you sleep? When I'm tired. :-) It's almost midnight here. I'm actually heading to bed here in just a few. > >just as if the code had been used as "int i = *pi;" would've done. Best regards, Rick C. Hodgin |
red floyd <no.spam.here@its.invalid>: May 07 10:04PM -0700 On 5/7/2016 6:21 PM, Jerry Stuckle wrote: >> Rick C. Hodgin > But you said it was impossible to have a reference to NULL. I just > pointed out that is NOT the fact. So your argument is false. No, because initializing the reference invokes UB. Dereferencing a NULL pointer is always UB. At that point, anything can happen, including, as you know, *appearing* to "work properly". |
Paavo Helde <myfirstname@osa.pri.ee>: May 08 08:43AM +0300 On 8.05.2016 2:52, Jerry Stuckle wrote: > } > Output: > The address of cr is 0 This program exhibits undefined behavior, so it is not guaranteed at all that it outputs "The address of cr is 0" (or that it outputs anything at all). A debugging implementation might have terminated the program already earlier. So I agree with Rick in that "references have utility in that you don't need to check if they're NULL". In more detail, there is no need to check against "NULL references" because a) the program must have exhibited UB first, so it's not sure how it behaves and it's not guaranteed that the check is reached at all. b) the check may be optimized out by the compiler as it relies on UB, meaning it is not reliable. c) if the check triggers, there is not much to do: you know that your program state is invalid so about the only sane thing to do is to call std::terminate(). But this will happen most probably anyway in the next code line which tries to use the object, so there is not much point. d) if the check triggers and the program continues to run, then you have just hidden an UB bug in the program, which may expose itself again in a different way in the most inappropriate time. The correct place to check is to check the pointer before creating the reference: int main (void) { int *pi = NULL; assert(pi); int &ri = *pi; callByRef(ri); } Checking against "NULL references" becomes viable only if the implementation defines the behavior, so that it's not UB any more. For example, MS seems to have done so in MSVC as they check against this==NULL in some of their code (implementation of MFC CWnd::GetSafeHwnd() et al). However, I believe this behavior is not publicly documented, which means it can change in the next compiler version or whatever and only MSVC itself can rely on it. As to why "NULL references" are undefined behavior, see 8.3.2/5 [dcl.ref]: <quote> A reference shall be initialized to refer to a valid object or function. [ Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the "object" obtained by indirection through a null pointer, which causes undefined behavior. </quote> |
"Öö Tiib" <ootiib@hot.ee>: May 07 10:50PM -0700 On Sunday, 8 May 2016 06:08:30 UTC+3, Jerry Stuckle wrote: > And I proved you wrong. There is nothing illegal in my code, nor is > there a sneaky trick. It's just a very simplified example of what can > easily happen, and the reference param is NULL. The C++ standard however proves you wrong. (8.3.2/4 "References"): | Note: in particular, a null reference cannot exist in a | well-defined program, because the only way to create such a reference | would be to bind it to the "object" obtained by dereferencing a null | pointer, which causes undefined behavior. That is exactly what you did. Therefore what you have there is not reference to NULL but a reference to demons from your nose. > I could have done something fancier - like set up a linked list and pass > a reference to a list element. But one past the end of the list would > have been a reference to NULL. So it would have been same defect. It feels that you are trolling again by posting code with undefined behavior. |
"Öö Tiib" <ootiib@hot.ee>: May 08 01:11AM -0700 On Saturday, 7 May 2016 23:48:54 UTC+3, Rick C. Hodgin wrote: > skip_whitepsaces(data, @offset, length); > I would've recognized that character there and said silently to myself, > "Ah ha!" It was really named "skip_whitepsaces"? It has indeed odd for C++ signature. More usual to C++ is to use iterators or ranges on such cases instead of indexes, lengths and offsets. Most readable calling for same (IMHO) would be something among: start.skip_whitespace(finish); start.skip(whitespaces, finish); range.left_trim_whitespace(); range.left_trim(whitespaces); Those may be not convenient to achieve in C++ sometimes but would look more obvious what there is going on. > something else? We use & for address-of, which is associated with a > pointer, but we also use it for a reference? Really? It seemed > backwards. Perhaps then try it out if more such symbols makes it possible to achieve more readable code. > It is much less than C++, but brings to C many of the essential elements > of C++ (as I see them, and there's room for expansion or contraction as > other people provide input). Does your language have also "this" like in C++? Perhaps make it a reference. It is pointer in C++ that can't be changed and may not be NULL so it is actually a reference with pointer syntax. |
Bo Persson <bop@gmb.dk>: May 08 11:02AM +0200 On 2016-05-08 07:43, Paavo Helde wrote: > CWnd::GetSafeHwnd() et al). However, I believe this behavior is not > publicly documented, which means it can change in the next compiler > version or whatever and only MSVC itself can rely on it. I believe this is the same as when Qt does it - the framework developers try to handle bug reports by "fixing" the code. They likely never checked this with the compiler team. Bo Persson |
"Öö Tiib" <ootiib@hot.ee>: May 08 03:55AM -0700 On Sunday, 8 May 2016 12:02:35 UTC+3, Bo Persson wrote: > I believe this is the same as when Qt does it - the framework developers > try to handle bug reports by "fixing" the code. They likely never > checked this with the compiler team. Often such "bug fixes" that rely on black wizardry with undefined behaviors are asshole-originated. For example some unskilled manager failed to dodge a blame and so his team has to implement that hack or to fail. Same can happen with compiler developers. For example when some benchmark code (that management has accepted) contains undefined behavior then it can be easier (for compiler team) to achieve the expected outcome instead of trying to argue that it is because of defect in benchmark. |
Jerry Stuckle <jstucklex@attglobal.net>: May 08 11:20AM -0400 On 5/7/2016 11:28 PM, Rick C. Hodgin wrote: > compiler did not catch it at runtime highlights a flaw in the compiler and > or C++ standard, because the error you created should never have been > allowed to occur. No, it is not illegal. It actually is undefined behavior. And the compiler is not *supposed* to catch it at runtime. What you don't get is, both C and C++ require a higher level of responsibility from the programmer. Neither generates unnecessary runtime check code. That's YOUR job. It's no different than going out of bounds on an array. That's the programmer's problem, not the language's. <snip> > just as if the code had been used as "int i = *pi;" would've done. > Best regards, > Rick C. Hodgin What you believe is immaterial, Rick. Neither C nor C++ generates unnecessary code to check for programming errors. If such a test is required, it is the responsibility of the programmer. And it also will not generate code to check "int i = *pi;". That is also undefined behavior. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
Jerry Stuckle <jstucklex@attglobal.net>: May 08 11:25AM -0400 On 5/8/2016 1:50 AM, Öö Tiib wrote: > | pointer, which causes undefined behavior. > That is exactly what you did. Therefore what you have there is not > reference to NULL but a reference to demons from your nose. Yes, and it is "undefined behavior" - not "illegal". A huge difference. > So it would have been same defect. > It feels that you are trolling again by posting code with undefined > behavior. But it is not "illegal". No trolling - just pointing out that Rick's statement that a reference cannot be NULL is incorrect. <snip> -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
Jerry Stuckle <jstucklex@attglobal.net>: May 08 11:26AM -0400 On 5/8/2016 1:04 AM, red floyd wrote: > No, because initializing the reference invokes UB. Dereferencing > a NULL pointer is always UB. At that point, anything can happen, > including, as you know, *appearing* to "work properly". That is correct. It is undefined behavior. But it is not illegal, and it can happen - despite Rick's claim. -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
Jerry Stuckle <jstucklex@attglobal.net>: May 08 11:28AM -0400 On 5/8/2016 1:43 AM, Paavo Helde wrote: > bind it to the "object" obtained by indirection through a null pointer, > which causes undefined behavior. > </quote> That all is well and good. But undefined behavior does not mean a reference cannot be NULL. Just that there is no guarantee what will happen if it is NULL. I don't disagree there are better ways of handling it. But that doesn't always happen, does it? -- ================== Remove the "x" from my email address Jerry Stuckle jstucklex@attglobal.net ================== |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 08 09:57AM -0700 On Sunday, May 8, 2016 at 11:20:11 AM UTC-4, Jerry Stuckle wrote: > > or C++ standard, because the error you created should never have been > > allowed to occur. > No, it is not illegal. Scarcely a difference, Jerry. And it still fits my definition of when references can be NULL. Here's something for you to try to educate yourself: Create a legal and valid coding example (one that doesn't involve UB) where you can legitimately create a NULL reference in C++. > It actually is undefined behavior. And the > compiler is not *supposed* to catch it at runtime. I said it, "highlights a flaw in the compiler and or C++ standard," because in my estimation the compiler should catch those things. Since references are never supposed to be NULL, passing a value as a reference derived from a pointer should enforce the non-NULL nature of the pointer by doing a simple memory read at that address. It would prevent this hole you've exploited via the arena of illegal coding practices, which you will say is only "UB" and not "illegal." It's fundamental. > What you don't get is, both C and C++ require a higher level of > responsibility from the programmer. Neither generates unnecessary > runtime check code. That's YOUR job. What you don't get, and never seem to get, is that I don't care what it's doing today. I'm looking toward what it SHOULD be doing because I don't want 40 more years to pass by and we're still using legacy baggage designed in the 1970s because of the limitations of those machines back in the day. I want a language that is very much C/C++ -like, but without some of the peculiarities we are forced to deal with for legacy reasons. I think the C Standard, and that which fed into the C++ standard, take a backwards approach on things. I think there should be defined a core set of abilities which are guaranteed, and then you can add on additional extensions and relaxations on top of that core, but within the core you address specific needs of data processing on the target for which that core was written (a two's complement machine with same- sized pointers, for example). > It's no different than going out of bounds on an array. That's the > programmer's problem, not the language's. In this case, that was my point exactly, because we're dealing with what exists today in C++. You should've checked for NULL so as to never have created the illegal reference in the first place. > > code to perform the NULL check right there, to catch the error at its cause, > > just as if the code had been used as "int i = *pi;" would've done. > What you believe is immaterial, Rick. I have no desire to wallow in what we have today, Jerry. I'm looking at fundamental requirements of data processing, and I'm constructing CAlive to begin there. > Neither C nor C++ generates > unnecessary code to check for programming errors. If such a test is > required, it is the responsibility of the programmer. In C/C++ that's the case. I'm looking to the future. I'm looking for more. I wonder if you'll ever be able to grasp that concept, Jerry? > And it also will not generate code to check "int i = *pi;". That is > also undefined behavior. Since you didn't get it, I'll be more clear: my point was the compiler should try to reference data at the pointer's location before assigning it to a reference. ----- This will be my last reply to you, Jerry. Possibly the last one ever. I wish you well, so I offer you a bit of advice: seek the Lord's guidance before you reply to people. You'll find so much of what you write is designed solely to be argumentative and obstinate, and in no way helpful. You cause much harm in the forums you post because of your horrendous attitude and large self-satiating ego. If you don't bring those aspects of your character into check, they will be your undoing because they will continuously lead you into all manner of places where there is no profit, to places no person should ever go. You have professed to be a Christian, so I advise you: humble yourself before the Lord, Jerry. And then go forth. Best regards, Rick C. Hodgin |
"K. Frank" <kfrank29.c@gmail.com>: May 07 05:29PM -0700 Hello Group! I (often) think of template classes as providing compile-time "polymorphism." Is it fair to think of concepts as interfaces for templates? If so, is it highly precise to think of concepts as interfaces for templates, or would it be more just a useful analogy, but "don't push it to far?" Thanks. K. Frank |
"Öö Tiib" <ootiib@hot.ee>: May 07 06:10PM -0700 On Sunday, 8 May 2016 03:30:11 UTC+3, K. Frank wrote: > I (often) think of template classes as providing > compile-time "polymorphism." Is it fair to think > of concepts as interfaces for templates? No ... I have had impression that the concepts are sets of constraints to any types. IOW ordinary class type or even fundamental type may fit with a concept. The checks of constraints is currently sometimes done by using various template metaprogamming tricks, type traits and std::enable_if. The concepts will hopefully simplify that. > If so, is it highly precise to think of concepts > as interfaces for templates, or would it be more > just a useful analogy, but "don't push it to far?" Perhaps don't push it too far. ;) |
Marcel Mueller <news.5.maazl@spamgourmet.org>: May 08 09:13AM +0200 On 08.05.16 02.29, K. Frank wrote: > I (often) think of template classes as providing > compile-time "polymorphism." Is it fair to think > of concepts as interfaces for templates? From the programmers point of view I wold say yes. From the technical point of view they are totally different. > If so, is it highly precise to think of concepts > as interfaces for templates, or would it be more > just a useful analogy, but "don't push it to far?" Well, at the end the question is, what you summarize with the term 'interface'. Marcel |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: May 08 04:41PM +0100 On Sat, 7 May 2016 17:29:59 -0700 (PDT) > If so, is it highly precise to think of concepts > as interfaces for templates, or would it be more > just a useful analogy, but "don't push it to far?" Concepts are type classes. They describe a subset of the set of all types, namely those that meet the concept requirements. If you find unnecessary OO an abstraction which you particularly like (I don't, I find it often adds obscurity) then I guess interfaces is one way of thinking about them, as a subset of the set of all inheritable implementation specifications. However at the end of the day they are just a named set of type constraints. So why not think of them as they are? |
"K. Frank" <kfrank29.c@gmail.com>: May 08 09:50AM -0700 Hello All! > > If so, is it highly precise to think of concepts > > as interfaces for templates, or would it be more > > just a useful analogy, but "don't push it to far?" Öö Tiib: > IOW ordinary class type or even fundamental type may fit with a concept. Yes, good point. A class need not know or care about a concept it satisfies. The concept could well be defined after the class. (See below.) Marcel Mueller: > Well, at the end the question is, what you summarize > with the term 'interface'. By "interface" I mean pretty much what java interfaces are, or what you get in c++ when you derive from a pure abstract base class: struct InterfaceA { virtual void methodA1() = 0; virtual void methodA2() = 0; virtual void methodA3() = 0; }; struct ClassImpA : InterfaceA { void methodA1() {} void methodA2() {} void methodA3() {} }; On Sunday, May 8, 2016 at 11:41:39 AM UTC-4, Chris Vine wrote: > implementation specifications. > However at the end of the day they are just a named set of type > constraints. So why not think of them as they are? Well, yes, this is certainly true. But my question is driven by why you would want to use a concept. I guess from the perspective of using a function argument, concepts are like interfaces: template <typename T "satisfies ConceptA"> void f (T& someA) { // do stuff that relies on ConceptA // true, ConceptA is a named set of type constraints, // but why would I care to name it? Because I care // that for the purposes of this function someA "is a" // ConceptA. } vs. void f (InterfaceA& someA) { someA.methodA3(); someA.methodA1(); } But from the perspective of defining a class, concepts and interfaces are different: struct ClassImpA : InterfaceA { ... }; ClassImpA had better implement InterfaceA, and the compiler will check that it does. Note, in particular, that for a ClassImpA to be passed to f (InterfaceA&), InterfaceA has to be defined in the translation unit of ClassImpA. But a class that satisfies a concept need not know about the concept (and the concept may not even have been defined yet), and, as Öö reminds us, even fundamental types can satisfy concepts. struct SomeClassThatHappensToSatisfyConceptA { // or maybe it doesn't ... }; Speaking of which, are there any concept proposals that permit or encourage classes to formally specify which concepts they intend to satisfy (and will be verified to satisfy)? Thanks for everyone's thoughts on this. K. Frank |
Ramine <ramine@1.1>: May 08 12:24PM -0700 Hello..... My C++ synchronization objects library was extended.. I have just included a Threadpool based on Pthread inside my C++ synchronization objects library.. You can download my C++ synchronization objects library from: https://sites.google.com/site/aminer68/c-synchronization-objects-library Thank you, Amine Moulay Ramdane. |
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