- Do not understand why I am getting these warnings ... - 10 Updates
- Memory Management Techniques - 3 Updates
- the magic embedded object - 3 Updates
- Another test of zapcc - 2 Updates
- Threaded Tree Causes SegFault - 1 Update
- accessing vectors embedded in class objects - 1 Update
mark <mark@invalid.invalid>: Nov 29 01:24PM +0100 On 2016-11-29 06:53, Alf P. Steinbach wrote: > support compilation with g++. > Cheers & hth., > - Alf Your code comes with security issues built in. Containers with more than INT_MAX elements aren't unheard of these days. In fact, I can allocate a vector<char> with more than INT_MAX elements with both 32-bit Linux and Windows programs. Your size_t -> ptrdiff_t conversion can overflow and you end up with a negative size value (you can get integer overflows and/or buffer overflows in downstream code on 8/16/32-bit platforms). Your int loop index can overflow if the container size is too large. For people compiling with warnings: clang -Wall -Wconversion -c test.cpp test.cpp:23:11: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long long') [-Wsign-conversion] v[i] = i; ~ ^ test.cpp:29:30: warning: implicit conversion changes signedness: 'unsigned long long' to 'const int' [-Wsign-conversion] int const j = rand() % v.size(); ~ ~~~~~~~^~~~~~~~~~ test.cpp:29:23: warning: implicit conversion changes signedness: 'int' to 'unsigned long long' [-Wsign-conversion] int const j = rand() % v.size(); ^~~~~~ ~ test.cpp:30:17: warning: implicit conversion changes signedness: 'int' to 'size_type' (aka 'unsigned long long') [-Wsign-conversion] swap( v[i], v[j] ); ~ ^ test.cpp:30:23: warning: implicit conversion changes signedness: 'const int' to 'size_type' (aka 'unsigned long long') [-Wsign-conversion] swap( v[i], v[j] ); ~ ^ test.cpp:12:12: warning: implicit conversion changes signedness: 'size_type' (aka 'unsigned long long') to 'Size' (aka 'long long') [-Wsign-conversion] { return c.size(); } ~~~~~~ ~~^~~~~~ test.cpp:21:25: note: in instantiation of function template specialization 'n_items_of<std::vector<int, std::allocator<int> > >' requested here for( int i = 1; i < n_items_of( v ); ++i ) ^ 6 warnings generated. |
"Öö Tiib" <ootiib@hot.ee>: Nov 29 07:32AM -0800 On Tuesday, 29 November 2016 14:25:06 UTC+2, mark wrote: > INT_MAX elements aren't unheard of these days. In fact, I can allocate a > vector<char> with more than INT_MAX elements with both 32-bit Linux and > Windows programs. Sure, but conforming INT_MAX can't be smaller than size limit 10000 that is explicitly given in the code. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 29 06:45PM +0100 On 29.11.2016 13:24, mark wrote: >> Cheers & hth., >> - Alf > Your code comes with security issues built in. False. > Containers with more than INT_MAX elements aren't unheard of these days. True. > In fact, I can allocate a > vector<char> with more than INT_MAX elements with both 32-bit Linux and > Windows programs. True. > Your size_t -> ptrdiff_t conversion can overflow It can overflow on a 16-bit system. That means that the /language/ does not support what one tries to achieve on such 16-bit system, since `ptrdiff_t` is the type used for pointer differences -- hence the name. I am sure that you don't understand this, since you continue to say... > and you end up with a > negative size value (you can get integer overflows and/or buffer > overflows in downstream code on 8/16/32-bit platforms). False. > Your int loop index can overflow if the container size is too large. False, it's not too large. Don't choose types for some extraordinary situation that's very different than the ones you need to handle. For example, don't drive a tractor to work just because you can imagine that if you were doing something very different, like farm work, you'd need that tractor. I think you'll agree that someone driving a tractor to work, for that reason, is behaving like an idiot. > to 'size_type' (aka 'unsigned long long') > [-Wsign-conversion] > v[i] = i; I didn't know that g++ supported that silly-warning. If you enable it then you truly deserve the meaningless avalanche of warnings. Cheers & hth., - Alf |
mark <mark@invalid.invalid>: Nov 29 09:29PM +0100 On 2016-11-29 18:45, Alf P. Steinbach wrote: > achieve on such 16-bit system, since `ptrdiff_t` is the type used for > pointer differences -- hence the name. > I am sure that you don't understand this, since you continue to say... It's not my fault that C++ is one big steaming pile of poo with regards to integers. Let's try a 32-bit platform (I'm too lazy to get out a 16-bit one), Linux i686, GCC 4.9.2: ------------------------------------------------------------------- #include <vector> #include <limits> #include <iostream> #include <stdint.h> using namespace std; using Size = ptrdiff_t; template< class Container > auto n_items_of( Container const& c ) -> Size { return c.size(); } int main() { std::vector<char> v; v.resize(size_t(std::numeric_limits<int>::max()) + 10); std::cout << "size(): " << v.size() << std::endl; std::cout << "n_items_of (s): " << (int64_t) n_items_of(v) << std::endl; std::cout << "n_items_of (u): " << (uint64_t) n_items_of(v) << std::endl; } --------------------------------------------------------------------- size(): 2147483657 n_items_of (s): -2147483639 n_items_of (u): 18446744071562067977 I have seen exactly this kind of bug in production code (e.g. with people using 64-bit ints for large file access). >> negative size value (you can get integer overflows and/or buffer >> overflows in downstream code on 8/16/32-bit platforms). > False. See above. >> Your int loop index can overflow if the container size is too large. > False, it's not too large. It is not too large with your hard-coded size. It can easily be too large if vectors are passed around. 64-bit platform to avoid the size_t -> ptrdiff_t overflow: -------------------------------------------------------------------- #include <vector> #include <limits> #include <iostream> using namespace std; using Size = ptrdiff_t; template< class Container > auto n_items_of( Container const& c ) -> Size { return c.size(); } int main() { std::vector<char> v; v.resize(size_t(std::numeric_limits<int>::max()) + 10); for(int i = 0; i < n_items_of(v); i++) ; } -------------------------------------------------------------------- g++ -Wall -O2 -std=c++14 test_huge_vector_undef_behavior.cpp test_huge_vector_undef_behavior.cpp: In function 'int main()': test_huge_vector_undef_behavior.cpp:17:5: warning: iteration 2147483647u invokes undefined behavior [-Waggressive-loop-optimizations] for(int i = 0; i < n_items_of(v); i++) ; ^ test_huge_vector_undef_behavior.cpp:17:5: note: containing loop In this case, GCC "optimizes" this into an endless loop. It would easy to transform this code to corrupt the entire memory after v. > Don't choose types for some extraordinary situation that's very > different than the ones you need to handle. So how do you deal with the potential overflows above? Do you check the container size each time you insert something that it's not larger than INT_MAX? > need that tractor. > I think you'll agree that someone driving a tractor to work, for that > reason, is behaving like an idiot. Advice like yours directly contributes to the endless flow of security vulnerabilities in C and C++ programs. > I didn't know that g++ supported that silly-warning. > If you enable it then you truly deserve the meaningless avalanche of > warnings. As it turns out those warnings are entirely justified. Doing anything with mixed sizes or signedness is one giant minefield. |
mark <mark@invalid.invalid>: Nov 29 09:35PM +0100 On 2016-11-29 16:32, Öö Tiib wrote: >> Windows programs. > Sure, but conforming INT_MAX can't be smaller than size limit 10000 that > is explicitly given in the code. What's your point? I was responding to the generic advice "In general, just use `int`, the natural integer type for the platform". That's bound to lead to overflows on a 64-bit platform, since everything else uses size_t (and ptrdiff_t will be a larger type as well). There is a nice template function thrown in to silence valid compiler warnings about this. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 29 09:55PM +0100 On 29.11.2016 21:29, mark wrote: > size(): 2147483657 > n_items_of (s): -2147483639 > n_items_of (u): 18446744071562067977 As mentioned, the /language/ doesn't support this. `ptrdiff_t` is the type of a pointer difference expression, any pointer difference expression. And it overflows for this case, which means that you need to treat that exceptionally large array very specially: you need to avoid handing it to code with any possible pointer differences. In other words, you're out of bounds of the language. It is the single example where overflow occurs, and it's not relevant since * It's not supported by the language. * It does not occur in practice. * It's not even supported by Windows (although Windows can be configured to support it). Re the last point, a 32-bit Windows application, without special configuration of Windows, only has 2GB memory available to it. Since you're apparently unaware of this, thinking that the above example would not only be generally safe if it used size_t, but thinking that allocating over half of available address space to a byte array, in 32-bit code, has occurred at least once in the annals of software development, you prove that you're absolutely clueless. As I suspected. > I have seen exactly this kind of bug in production code (e.g. with > people using 64-bit ints for large file access). No doubt you have. It's so common allocating > 2G byte arrays in 32-bit code. Laughing out loud. :) Cheers!, & hth., - Alf |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 29 09:21PM On 29/11/2016 20:35, mark wrote: > just use `int`, the natural integer type for the platform". That's bound > to lead to overflows on a 64-bit platform, since everything else uses > size_t (and ptrdiff_t will be a larger type as well). One should not use 'int' at all in a C++ program (except as return type of main()) at it is unsafe and non-portable. One should used the sized integer typedefs such as int32_t instead. /Flibble |
legalize+jeeves@mail.xmission.com (Richard): Nov 29 10:02PM [Please do not mail me a copy of your followup] mark <mark@invalid.invalid> spake the secret code >It's not my fault that C++ is one big steaming pile of poo with regards >to integers. Pray tell, what languages are addressing this in a superior fashion? -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Terminals Wiki <http://terminals-wiki.org> The Computer Graphics Museum <http://computergraphicsmuseum.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
mark <mark@invalid.invalid>: Nov 29 11:13PM +0100 On 2016-11-29 21:55, Alf P. Steinbach wrote: > As mentioned, the /language/ doesn't support this. `ptrdiff_t` is the > type of a pointer difference expression, any pointer difference > expression. The language is broken. ptrdiff_t doesn't need to support arbitrary pointer differences, 5.7 [expr.add]: <<< When two pointers to elements of the same array object are subtracted, the result is the difference of the subscripts of the two array elements. The type of the result is an implementation-defined signed integral type; this type shall be the same type that is defined as std::ptrdiff_t in the <cstddef> header (18.2). As with any other arithmetic overflow, if the result does not fit in the space provided, the behavior is undefined. Your n_items_of() has undefined behavior. From what I can tell, the only restriction on ptrdiff_t is that it is signed. But apparently, per C and C++ standards, it could theoretically be int8_t and it could be a smaller type than size_t. > And it overflows for this case, which means that you need to > treat that exceptionally large array very specially: you need to avoid > handing it to code with any possible pointer differences. How do you know in advance how large the array is? > In other words, you're out of bounds of the language. ??? > It is the single example where overflow occurs, and it's not relevant since > * It's not supported by the language. The language supports an array size that's larger than ptrdiff_t. Why don't you point where standard disallows it, instead of throwing around insults? > * It does not occur in practice. It does occur in practice. > to support it). > Re the last point, a 32-bit Windows application, without special > configuration of Windows, only has 2GB memory available to it. 32-bit programs running on x64 Windows get 4GB of address space without any special configuration. They just need to be compiled with the "largeaddressaware" flag. >> people using 64-bit ints for large file access). > No doubt you have. It's so common allocating > 2G byte arrays in 32-bit > code. Did I say it's common? It was a security bug. A large vector was allocated shortly after program start, the size being calculated based on untrusted input. Eventually, there was a comparison between the size and an int variable leading to memory corruption. The same kind of thing can happen on platforms where int == int16_t, size_t == uint16_t, ptrdiff_t == int. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 29 11:55PM +0100 On 29.11.2016 23:13, mark wrote: >> type of a pointer difference expression, any pointer difference >> expression. > The language is broken. Wrong about this. > ptrdiff_t doesn't need to support arbitrary pointer differences, Right. > std::ptrdiff_t in the <cstddef> header (18.2). As with any other > arithmetic overflow, if the result does not fit in the space provided, > the behavior is undefined. Good. > Your n_items_of() has undefined behavior. Wrong. > From what I can tell, the only restriction on ptrdiff_t is that it is > signed. But apparently, per C and C++ standards, it could theoretically > be int8_t and it could be a smaller type than size_t. No, it's required, by the C standard, to be at least 17 bits. And that's not a typo, I didn't mean to write 16. >> treat that exceptionally large array very specially: you need to avoid >> handing it to code with any possible pointer differences. > How do you know in advance how large the array is? You don't, in general. Just like you don't know exactly the required stack size. And there are other problems with such (relative to 32-bit coding) large arrays, including that an OS built on the idea that we-at-Microsoft-make-software-that-know-better-than-you-what-you-need such as Windows, can just start trashing, swapping to and back from disk, with no way to configure off that behavior. >> In other words, you're out of bounds of the language. > ??? The core language doesn't support that array size in general, due to the fact that the type of a pointer difference is `ptrdiff_t`. The standard library does not support it, since it also defaults its difference types, e.g. for `std::distance`, to `ptrdiff_t`. >> * It's not supported by the language. > The language supports an array size that's larger than ptrdiff_t. Why > don't you point where standard disallows it, You just did, above. It's not disallowed. It's just /partly/ supported. Which means it's not generally or fully supported. You have to be very careful what you do with it, lest things go haywire. > instead of throwing around insults? Oh, sorry about that. We'll see where this goes. >> * It does not occur in practice. > It does occur in practice. Fire those devs. > 32-bit programs running on x64 Windows get 4GB of address space without > any special configuration. They just need to be compiled with the > "largeaddressaware" flag. Well, there's more to it than that, including bugs in the Windows API (i.e., be careful with axe, Eugene), but the main sub-point is that this example, the single one of its kind, does not occur naturally. That's probably why the language design, the limits of pointer arithmetic, simply assumes that it doesn't occur. [snip] > allocated shortly after program start, the size being calculated based > on untrusted input. Eventually, there was a comparison between the size > and an int variable leading to memory corruption. A bug in someone's program means that the function I presented was unsafe, for they could in theory have used that function in their buggy code, yes? No. It doesn't work that way. A function isn't unsafe because it's possible for someone's buggy code to give it arguments outside its preconditions. > The same kind of thing can happen on platforms where int == int16_t, > size_t == uint16_t, ptrdiff_t == int. No, `ptrdiff_t` is not allowed to be 16 bits or less. In a conforming implementation. Because the C standard requires its limits to be equal or greater in magnitude to −65535 (lower limit) and +65535 (upper limit). Cheers & hth., - Alf |
asetofsymbols@gmail.com: Nov 29 11:55AM -0800 Allocator? What does it mean? If it is malloc() free() implementation there is K&R2 that says in its pages, where to start, I remember from that custom malloc is possible implement C++ memory operators new() delete() too |
"Öö Tiib" <ootiib@hot.ee>: Nov 29 12:13PM -0800 > there is K&R2 that says in its pages, where to start, I remember from > that custom malloc is possible implement C++ memory operators > new() delete() too No, it is C++ class interface concept of Allocator. Standard library provides standard Allocator template that is named 'std::allocator'. All standard templates that expect allocator argument have it as default. So for example 'std::vector' takes two arguments: template< class T , class Allocator = std::allocator<T> > class vector; |
"Christopher J. Pisz" <cpisz@austin.rr.com>: Nov 29 02:54PM -0600 On 11/29/2016 2:13 PM, Öö Tiib wrote: > template< class T > , class Allocator = std::allocator<T> > > class vector; No, the word 'allocator' did not appear in the original post at all. So it means nothing, because it isn't there to begin with. |
ruben safir <ruben@mrbrklyn.com>: Nov 29 04:39AM -0500 Why is it that when I change the origianl vector the object changes but not the reverse. #include <iostream> #include <vector> namespace vect{ /* * ===================================================================================== * Class: Lvalue * Description: testing vector access as an lvalue * ===================================================================================== */ template < class T > class Lvalue { public: // ==================== LIFECYCLE ======================================= Lvalue (){}; /* constructor */ Lvalue (std::vector<T> in): _ofthings{in}{}; /* constructor */ Lvalue ( const Lvalue &other ); /* copy constructor */ ~Lvalue (){}; /* destructor */ /* ==================== ACCESSORS ======================================= */ std::vector<T>& ofthings(){ return _ofthings; }; void ofthings(std::vector<T> const vec){ _ofthings = vec; }; /* ==================== MUTATORS ======================================= */ /* ==================== OPERATORS ======================================= */ const Lvalue& operator = ( const Lvalue &other ); // assignment operator T& operator [] (int index) { return (ofthings()[index]); }; friend std::ostream &operator << (std::ostream &os, const Lvalue in) { for(int i = 0; i < in._ofthings.size(); i++ ){ std::cout << i << "\t"; } return os; }; /* ==================== DATA MEMBERS ======================================= */ protected: std::vector<T> _ofthings; private: }; /* ----- end of template class Lvalue ----- */ }; int main ( int argc, char *argv[] ) { std::cout << "TEST INPUT TO VECTOR" << std::endl; std::vector<int> test(100, 0); for(int i = 0; i<10; i++ ){ test[i] = i; std::cout << i << "::" <<test[i] << "\t"; } std::cout << std::endl; std::cout << "TEST INPUT TO OBJECT" << std::endl; vect::Lvalue<int> test2 {test}; for(int j = 0, i=10; j < 10; i--, j++){ test[j] = i; std::cout << "What is J" << j << std::endl; std::cout << "i: " << i << " j: " << j << " test[j]: " << test[j] << std::endl; std::cout << "i: " << i << " j: " << j << " test2[j]: " << test[j] << std::endl; } std::cout << std::endl; std::cout << "TEST INPUT TO OBJECT bidirectional" << std::endl; for(int i = 0, j=10; i < 10; i++, j++){ test2[i] = j; std::cout << "What is i ==>" << i << std::endl; std::cout << "i: " << i << " j: " << j << " test2[i]: " << test2[i] << std::endl; std::cout << "i: " << i << " j: " << j << " test[i]: " << test[i] << std::endl; } std::cout << std::endl; std::cout << std::endl; for(int j = 0, i=10; j < 10; i--, j++){ test[j] = i; std::cout << "What is J" << j << std::endl; std::cout << "i: " << i << " j: " << j << " test[j]: " << test[j] << std::endl; std::cout << "i: " << i << " j: " << j << " test2[j]: " << test[j] << std::endl; } std::cout << "__DONE__" << std::endl; return EXIT_SUCCESS; } /* ---------- end of function main ---------- */ TEST INPUT TO VECTOR 0::0 1::1 2::2 3::3 4::4 5::5 6::6 7::7 8::8 9::9 TEST INPUT TO OBJECT What is J0 i: 10 j: 0 test[j]: 10 i: 10 j: 0 test2[j]: 10 What is J1 i: 9 j: 1 test[j]: 9 i: 9 j: 1 test2[j]: 9 What is J2 i: 8 j: 2 test[j]: 8 i: 8 j: 2 test2[j]: 8 What is J3 i: 7 j: 3 test[j]: 7 i: 7 j: 3 test2[j]: 7 What is J4 i: 6 j: 4 test[j]: 6 i: 6 j: 4 test2[j]: 6 What is J5 i: 5 j: 5 test[j]: 5 i: 5 j: 5 test2[j]: 5 What is J6 i: 4 j: 6 test[j]: 4 i: 4 j: 6 test2[j]: 4 What is J7 i: 3 j: 7 test[j]: 3 i: 3 j: 7 test2[j]: 3 What is J8 i: 2 j: 8 test[j]: 2 i: 2 j: 8 test2[j]: 2 What is J9 i: 1 j: 9 test[j]: 1 i: 1 j: 9 test2[j]: 1 TEST INPUT TO OBJECT bidirectional What is i ==>0 i: 0 j: 10 test2[i]: 10 i: 0 j: 10 test[i]: 10 What is i ==>1 i: 1 j: 11 test2[i]: 11 i: 1 j: 11 test[i]: 9 What is i ==>2 i: 2 j: 12 test2[i]: 12 i: 2 j: 12 test[i]: 8 What is i ==>3 i: 3 j: 13 test2[i]: 13 i: 3 j: 13 test[i]: 7 What is i ==>4 i: 4 j: 14 test2[i]: 14 i: 4 j: 14 test[i]: 6 What is i ==>5 i: 5 j: 15 test2[i]: 15 i: 5 j: 15 test[i]: 5 What is i ==>6 i: 6 j: 16 test2[i]: 16 i: 6 j: 16 test[i]: 4 What is i ==>7 i: 7 j: 17 test2[i]: 17 i: 7 j: 17 test[i]: 3 What is i ==>8 i: 8 j: 18 test2[i]: 18 i: 8 j: 18 test[i]: 2 What is i ==>9 i: 9 j: 19 test2[i]: 19 i: 9 j: 19 test[i]: 1 What is J0 i: 10 j: 0 test[j]: 10 i: 10 j: 0 test2[j]: 10 What is J1 i: 9 j: 1 test[j]: 9 i: 9 j: 1 test2[j]: 9 What is J2 i: 8 j: 2 test[j]: 8 i: 8 j: 2 test2[j]: 8 What is J3 i: 7 j: 3 test[j]: 7 i: 7 j: 3 test2[j]: 7 What is J4 i: 6 j: 4 test[j]: 6 i: 6 j: 4 test2[j]: 6 What is J5 i: 5 j: 5 test[j]: 5 i: 5 j: 5 test2[j]: 5 What is J6 i: 4 j: 6 test[j]: 4 i: 4 j: 6 test2[j]: 4 What is J7 i: 3 j: 7 test[j]: 3 i: 3 j: 7 test2[j]: 3 What is J8 i: 2 j: 8 test[j]: 2 i: 2 j: 8 test2[j]: 2 What is J9 i: 1 j: 9 test[j]: 1 i: 1 j: 9 test2[j]: 1 __DONE__ |
Ben Bacarisse <ben.usenet@bsb.me.uk>: Nov 29 10:45AM > Why is it that when I change the origianl vector the object changes > but not the reverse. Neither is happening. You've missed a "2" from the two ouput operations. <snip> -- Ben. |
ruben safir <ruben@mrbrklyn.com>: Nov 29 09:29AM -0500 On 11/29/2016 05:45 AM, Ben Bacarisse wrote: > Neither is happening. You've missed a "2" from the two ouput operations. correct, thanks for looking |
David Brown <david.brown@hesbynett.no>: Nov 29 09:59AM +0100 > are doing (making the compiler a server) is a good idea? > Sorry to honk my own horn again, but I suggested this with > GCC before Clang existed. You can blow your nose as much as you want, but it was hardly /your/ idea. The idea of making a compilation server has existed for decades - certainly for the twenty+ years that I have been programming C. And it is precisely to avoid people taking all the hard work of gcc and putting it into a closed-source commercial product that gcc have long insisted on a traditional compilation model, rather than considering a server-style system. The clang/llvm folks differ in their philosophy for licenses, and see the use of clang as a server (especially in IDEs) as a major use case. gcc /is/ moving towards better support for server-style compilation (in particular, for use with gdb), just as they introduced a plugin architecture a few years ago despite fears that it would be easier to mix gcc with closed-source software. |
"Öö Tiib" <ootiib@hot.ee>: Nov 29 06:19AM -0800 On Monday, 28 November 2016 23:44:58 UTC+2, Vir Campestris wrote: > > compilation. Whatever they have done is closed source and in beta test. > Is that even legal? Surely Clang's licence requires you to publish > derived works? (asd no, I haven't checked) It is legal to make closed source derivative work from clang code base. My opinion is that if there are such things then clang has more usages and so becomes better and it is good. |
Paavo Helde <myfirstname@osa.pri.ee>: Nov 29 10:29AM +0200 On 29.11.2016 0:50, xerofoify wrote: >> } >> Moreover, if here p->data_==data, this thing goes into infinite loop. > I am still confused Paavo. Can you show me through code as it seems like I am not understanding it for some reason. I am not sure what you are confused about. Pointers? Basic execution flow? From afar, it looks like you are using some kind of Monte Carlo programming style - writing down a random sequence of tokens, hoping that this somehow works and does whatever is needed. This is bound to be a very tedious method and certainly does not work in C++ where a program might appear to work correctly and still exhibit Undefined Behavior. Maybe you should first try a simpler program involving pointers? Anyway, if stepping through debugger does not help you, write down the state on the paper (values for the memory slots occupied by p, data, etc) and step through the code on paper. > iterator begin(){ > Node* curr = root_; > if (curr->right_ == nullptr && curr->left_ == nullptr) { For example, here you dereferenced 'curr'. > return nullptr; > } > if (curr != nullptr) { And only here you check if it can be dereferenced. See a problem here? Either the check is in the wrong place or it is not needed. > return iterator(curr); > } > Look I have tried this for at least a few things now and ran through a debugger many times guys. Something is not clicking in my understanding so asking me to run through it with a debugger does not help. This version also has no mention of leftThread or rightThread, which were apparently needed in the previous version. I have no idea what this function should do, so I do not know if they are needed or not, but it sure looks suspicious. hth Paavo |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 29 09:18AM +0100 On 29.11.2016 08:49, ruben safir wrote: >> Cheers!, >> _ Alf > Alf, your off your rocker, truly. As far as I can tell Rubin Safir and Popping Mad are the same person. - Alf |
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