- static vector (c style) - 11 Updates
- Access Violation on a thread - 2 Updates
- Debugging a template. I'm stuck! - 7 Updates
- Journals on C++ - 3 Updates
- C++ for industrial automation - 2 Updates
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 27 12:25AM On Mon, 26 Jan 2015 16:30:24 -0600 > I'd sure like to know how the author intended to use this class, > because I question both making it static and using the c-array vs a > stl container. Clearly there is a use case for a statically sized container with contiguous storage or std::array would not be in C++11. And if the array is a non-static class member, it makes little difference whether you use a plain array or std::array because both have the same compiler generated copy constructor and assignment operator. That use case generally involves efficiency, because unlike std::vector arrays are not dynamically allocated (unless you explicitly new them, which is stupid because std::vector is available). For the cases I have mentioned, I use a plain array, partly because that is what I have done for years, and partly because ... why not? std::array permits a zero size and a plain array does not, but I have never written code requiring a zero size array. Whether it should be static member or not is orthogonal. If it is a static member, it is of even less importance whether it is a plain array or a std::array type. And maybe of course the OP was using C++98/03. Chris |
Christopher Pisz <nospam@notanaddress.com>: Jan 26 06:43PM -0600 On 1/26/2015 6:25 PM, Chris Vine wrote: > stupid because std::vector is available). For the cases I have > mentioned, I use a plain array, partly because that is what I have done > for years, and partly because ... why not? I often hear that same argument from C programmers: "std::vector allocates." If you are using a c-array, you must know the size before hand, and if you know the size before hand, you can create the vector with that size, so what are we really optimizing away in the name of efficiency? I suppose you could argue the one time allocation on the heap at construction time vs on the stack, if your class resides on the stack anyway. However, what are you really saving and what are you giving up? |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 27 12:57AM On Mon, 26 Jan 2015 18:43:56 -0600 Christopher Pisz <nospam@notanaddress.com> wrote: [snip] > construction time vs on the stack, if your class resides on the stack > anyway. However, what are you really saving and what are you giving > up? That is ridiculous. Allocation on the heap is a heavy-weight operation compared with allocation on the stack, relatively speaking, particularly in multi-threaded programs which require thread-safe allocation and deallocation. Dynamic allocation also reduces cache locality. Furthermore std::vector constructed with a particular initial size calls the default constructor for each element, so you sometimes have to reserve a size and then pushback onto it to avoid that. Are you seriously saying that in your code you always use std::vector instead of an array even when the size is known statically? And why do you think std::array is in C++11? The case for using std::vector even with statically known sizes is when you may carry out move operations, as moving vectors just requires swapping pointers. But you would still need to profile. I find your question disturbing. Chris |
Ian Collins <ian-news@hotmail.com>: Jan 27 08:09PM +1300 Christopher Pisz wrote: > I suppose you could argue the one time allocation on the heap at > construction time vs on the stack, if your class resides on the stack > anyway. However, what are you really saving and what are you giving up? Locality of reference? -- Ian Collins |
Juha Nieminen <nospam@thanks.invalid>: Jan 27 08:21AM > After all the discussion of profiling and virtual functions in child > threads, ....I still want to know why in the world anyone would want a > static C-Array in their C++ class. Because it's enormously more efficient. It's faster to allocate and deallocate (allocating memory for the array doesn't take any more additional time than allocating the instance of the class the array is inside). It consumes less memory. It does not contribute to memory fragmentation. Sure, in a class that's instantiated a few times it doesn't matter. However, in a class that's instantiated tens of thousands, or even millions of times, it matters quite a lot. --- news://freenews.netfront.net/ - complaints: news@netfront.net --- |
David Brown <david.brown@hesbynett.no>: Jan 27 11:23AM +0100 On 27/01/15 01:43, Christopher Pisz wrote: > hand, and if you know the size before hand, you can create the vector > with that size, so what are we really optimizing away in the name of > efficiency? 1. Allocating a block of data on the stack takes a couple of instructions - allocating it in heap can mean system calls, locks, threading issues, etc. (Typically a new/malloc implementation holds a local pool that can be quickly allocated, and only needs a system malloc to re-fill the local pool - so allocation times can vary between "not much" to "a lot", depending on the state of the local pool.) And allocating a block statically takes no instructions at all. If you are doing this once, dynamic allocation of a vector means wasting a few microseconds, which is obviously not a concern. But if you are doing it thousands of times, it adds up. 2. Static allocation, or at least stack allocation, is far more amenable to compile-time checking and (if necessary) faster run-time checks to help catch errors sooner. 3. Statically allocated data, or at least stack allocated data, requires fewer instructions and fewer registers to access, making it faster. It also has better locality of reference and is more likely to be in the cache, which can make a huge difference (this depends on the size of the data and the access patterns, of course). Coming from an embedded background, where this is often much more relevant than on desktop systems (partly because memory fragmentation on heaps is a serious issue when you don't have virtual memory), there is a clear golden rule that all allocations should be static if possible, with stack allocation as a second-best. In many embedded systems, dynamic allocation is not allowed at all - it is certainly never encouraged. |
Christopher Pisz <nospam@notanaddress.com>: Jan 27 09:28AM -0600 On 1/27/2015 4:23 AM, David Brown wrote: > If you are doing this once, dynamic allocation of a vector means wasting > a few microseconds, which is obviously not a concern. But if you are > doing it thousands of times, it adds up. Well, this is what I am getting at. If there is _one_ allocation, there is no need to apply a rule of "I won't use any STL container, because allocation!", which is often what I hear from C programmers. More often than not A) They are not even aware you can specify size at construction time for a vector or reserve size after if you wish B) They haven't even considered how often the container or class that owns the container is being constructed. > Static allocation, or at least stack allocation, is far more amenable to > compile-time checking and (if necessary) faster run-time checks to help > catch errors sooner. What exactly does "amenable to compile time checking" mean? "Run time checks to catch errors sooner?" What run time check is going to occur on a c-array? Run time checks would be a reason to use an STL container in the first place. Of course none is faster than some. > also has better locality of reference and is more likely to be in the > cache, which can make a huge difference (this depends on the size of the > data and the access patterns, of course). Not disagreeing with you, but I've never read any evidence of a contiguous block of memory on the stack vs a contiguous block of memory on the heap being more likely to be in the cache. Have anything to reference? > clear golden rule that all allocations should be static if possible, > with stack allocation as a second-best. In many embedded systems, > dynamic allocation is not allowed at all - it is certainly never encouraged. Well, that's the thing. I often work with C programmers whom came from a background where it was relevant, but then they adopt silly rules like "don't ever use an STL container, because 'allocation'" in places where the difference is negligible. You do, but I have my doubts that the OP did. I am willing to bet he was doing what he did, "just because", but we'll never know. |
Christopher Pisz <nospam@notanaddress.com>: Jan 27 09:40AM -0600 On 1/26/2015 6:57 PM, Chris Vine wrote: >> up? > That is ridiculous. Allocation on the heap is a heavy-weight > operation compared with allocation on the stack, No one is arguing otherwise. The thing I have a problem with is I often end up working with people whom use that as an excuse to never use an STL container at all, regardless of how often allocation may occur. > relatively speaking, > particularly in multi-threaded programs which require thread-safe > allocation and deallocation. std::vector<int>(10) is going to be the same whether my program is multithreaded or not. If there are thread safety concerners, then most likely the container would be inside some class and the same locking mechanisms are going to be added whether it is a std::vector, a c-array, or a snuffleupugus. > Dynamic allocation also reduces cache > locality. Someone else said this too. Not disagreeing, but I've never read it. Got a reference? > initial size calls the default constructor for each element, so you > sometimes have to reserve a size and then pushback onto it to avoid > that. but again, how long does it take to construct an int? It depends on the scenario and like I said, I suspect the OP was doing what he was doing just because "Me like meat. STL bad....C gud.", but looks like he lost interest in his topic. |
jak <please@nospam.tnx>: Jan 27 05:38PM +0100 Il 27/01/2015 16:40, Christopher Pisz ha scritto: > scenario and like I said, I suspect the OP was doing what he was doing > just because "Me like meat. STL bad....C gud.", but looks like he lost > interest in his topic. I have not lost interest, indeed, I follow you with attention. my problem was to serialize a resource. I use the static field in the class to save the state of the resource even when I declare a new variable of that class in the various functions to always know the situation of the resource. PS: I had to cut the rest of the discussion because my application gave me a sending error. sorry. |
Christopher Pisz <nospam@notanaddress.com>: Jan 27 11:04AM -0600 On 1/27/2015 10:38 AM, jak wrote: > PS: > I had to cut the rest of the discussion because my application gave me a > sending error. sorry. Oh , I thought some fellow named Alessio was the OP. You are using 2 different accounts then I suppose. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 27 07:51PM On Tue, 27 Jan 2015 09:40:12 -0600 > would be inside some class and the same locking mechanisms are going > to be added whether it is a std::vector, a c-array, or a > snuffleupugus. That's not the point. The heap is a global resource and the _heap manager_ has to deal with concurrency in a multi-threaded program. This has nothing to do with concurrent access to the same container (if you are going to have concurrent access to the same container you need to at least look at std::list if you are going to have a lot of contention). The fact that the heap manager has to cope with concurrency is one of the reasons why dynamic allocation has overhead. > > locality. > Someone else said this too. Not disagreeing, but I've never read it. > Got a reference? I cannot come up with a study (although I would be surprised if there wasn't one), but it must do so, because memory allocated on the heap will not be in the same cache line as the memory for the object itself. > the scenario and like I said, I suspect the OP was doing what he was > doing just because "Me like meat. STL bad....C gud.", but looks like > he lost interest in his topic. It's the cost of unnecessary zero initialization of built in types. Small, but it is there and if you can avoid it then why not? I just come back to the point that failing to make use of an array (or std::array) instead of std::vector where you have a statically (constexpr) sized container of built in types, just because you don't like C programming practices, seems crazy to me. It's a bit like failing to call std::reserve() on a vector when you actually know programmatically at run time what the final size of the vector will be, and instead just relying on the vector's normal algorithm to allocate memory in multiple enlarging steps as it is pushed onto. The code will still work but you will be doing unnecessary allocations of memory and copying or moving of vector elements. Don't do it if you can avoid it. Take the low hanging fruit. It is not premature optimization to follow a few simple rules which will make all your programs faster without any extra effort. Chris |
Christopher Pisz <nospam@notanaddress.com>: Jan 27 12:54PM -0600 Is there some defined standard behavior about what should happen should an Access Violation occur on a thread? My application is single threaded, and I see in my debugger it has 12 or so threads with COM and RPC and wininet crap. Everything in those threads is completely outside of my source. So, I assume some third party library (gsoap) is creating these threads. Randomly I get an Access Violation on one or more of these threads. Should I expect the process to terminate? or Should the thread terminate on its own? What is expected to happen if this occurs? |
Paavo Helde <myfirstname@osa.pri.ee>: Jan 27 01:34PM -0600 Christopher Pisz <nospam@notanaddress.com> wrote in news:ma8mse$gv4$1 > Is there some defined standard behavior about what should happen should > an Access Violation occur on a thread? > My application is single threaded, and I see in my debugger it has 12 or > or > Should the thread terminate on its own? > What is expected to happen if this occurs? Access violation is most usually caused by the program invoking Undefined Behavior, so anything can happen. Typically, in Linux world you could be pretty certain the process is killed in spot by the OS. However, in Windows world this is not so simple, the program can define handlers for "handling" these kind of errors. Windows also likes to display (mostly unhelpful) dialog boxes, sometimes offering a possibility to attach a debugger. As "anything can happen", all these behaviors are legal. Terminating a single thread is not an option as this is pretty much guaranteed to leave the process in an inconsistent state. Another a bit more reliable way is to "handle and ignore" the error, there are even Windows SDK idioms which actually do that in an encapsulated way (IsBadReadPtr() and friends) which can be greatly abused by crappy programs for hiding their bugs. If you can continue the program in the debugger after the access violation and nothing bad seems to happen, this probably means the code has "handled" the access violation in this or a similar way. Note that even if the problem appears in a foreign thread it does not mean that your code is not to blame. It could have passed some invalid data to the foregin thread directly or indirectly. hth Paavo |
DSF <notavalid@address.here>: Jan 26 11:41PM -0500 On Mon, 26 Jan 2015 21:57:06 +0000 (UTC), Tobias Müller >> Borland C/C++ 5.01A >> Yes, I know. >Do you realize that this is almost 20 years old? LOL! LOL! LOL! LOL! No offense meant, but thanks for the laugh! I have broken or at least severely bent causality by answering your question before you asked it, i.e. effect -> cause. >Tobi DSF "'Later' is the beginning of what's not to be." D.S. Fiscus |
DSF <notavalid@address.here>: Jan 27 03:22AM -0500 On Sun, 25 Jan 2015 14:28:05 -0500, DSF <notavalid@address.here> wrote: >Hello, group! I should mention in the very slight defense off my 25-year-old compiler that it does also highlight the line with the error and list its approximate location before the error. ! FAList.h(530,1):Illegal structure operation So I know what template it is in and I can translate the error to "The == operator is not a standard operator that can be used with structures (classes)." Meaning I have an instance somewhere of FAList<some_class> foo, where some_class has not overloaded ==. My problem being the message doesn't identify "some_class". I can't afford the time right now to learn my way around a new compiler. Not to mention all the source I'll have to recompile. And even though I have all warnings and errors enabled in my current moldy-oldie, I'm sure there will be *many* lines of code indigestible to the new compiler without tweaking. In fact, I have a compiler ready for installation in a virtual machine, but I need the use of the utility I'm writing (the one with this error) to have the disk space to set up the virtual machine. I've searched every file in the project and associated libraries for FAList< and every instance the class inside the angle brackets has an overloaded ==. I did encounter something unusual. I'll summarize it: class Foo { public: ...etc... friend bool operator==(const Foo& foo1, const Foo& foo2); ... }; inline bool operator==(const Foo& foo1, const Foo foo2) {do comparison}; Note the missing ampersand on the second Foo of the inline line. Shouldn't this be an error? The TU compiled with 0 errors and 0 warnings. BTW, adding the ampersand did not fix the main problem. Thanks for all your responses, DSF "'Later' is the beginning of what's not to be." D.S. Fiscus |
Rosario193 <Rosario@invalid.invalid>: Jan 27 09:23AM +0100 On Mon, 26 Jan 2015 16:00:28 -0500, DSF wrote: ... >DSF >"'Later' is the beginning of what's not to be." >D.S. Fiscus this compile and run here... #include <stdio.h> class Foo {public: Foo(int n): num(n){;} Foo(Foo& a){if(&a!=this) num=a.num;} friend int operator==(Foo& f1, Foo& f2); int num; }; int operator==(Foo& f1, Foo& f2){return f1.num==f2.num;} template<class T>class Tester {public: int CompareObject(T& obj){return object==obj;} Tester(T& obj):object(obj){;} T object; }; int main(void) {Foo fo1(12); Foo fo2(12); Tester<Foo> testfoo(fo1); int result=testfoo.CompareObject(fo2); printf("fo1 %s equal fo2\n", result ? "does" : "does not"); return 0; } |
Rosario193 <Rosario@invalid.invalid>: Jan 27 10:05AM +0100 On Tue, 27 Jan 2015 09:23:33 +0100, Rosario193 wrote: > printf("fo1 %s equal fo2\n", result ? "does" : "does not"); > return 0; >} _TEXT segment dword public use32 'CODE' @$beql$qr3Foot1 segment virtual @@$beql$qr3Foot1 proc near ?live16385@0: ; ; int operator==(Foo& f1, Foo& f2){return f1.num==f2.num;} ; push ebp mov ebp,esp @1: mov eax,dword ptr [ebp+8] mov edx,dword ptr [eax] mov ecx,dword ptr [ebp+12] cmp edx,dword ptr [ecx] sete al and eax,1 @3: @2: pop ebp ret @@$beql$qr3Foot1 endp @$beql$qr3Foot1 ends _TEXT ends _TEXT segment dword public use32 'CODE' _main segment virtual @_main proc near ?live16386@0: ; ; int main(void) ; push ebp mov ebp,esp add esp,-12 ; ; {Foo fo1(12); ; @4: mov dword ptr [ebp-4],12 ; ; Foo fo2(12); ; mov dword ptr [ebp-8],12 ; ; Tester<Foo> testfoo(fo1); ; lea eax,dword ptr [ebp-4] lea edx,dword ptr [ebp-12] cmp eax,edx je short @5 mov ecx,dword ptr [ebp-4] mov dword ptr [ebp-12],ecx here appear that is called "Foo(Foo& a){if(&a!=this) num=a.num;}" inline ; ; int result=testfoo.CompareObject(fo2); ; @5: @6: lea eax,dword ptr [ebp-8] push eax lea edx,dword ptr [ebp-12] push edx call @@$beql$qr3Foot1 add esp,8 here it call the right function int operator==(Foo& f1, Foo& f2){return f1.num==f2.num;} and printf result: ; ; ; printf("fo1 %s equal fo2\n", result ? "does" : "does not"); ; ?live16386@80: ; EAX = result test eax,eax je short @7 mov ecx,offset s@+18 jmp short @8 @7: mov ecx,offset s@+23 @8: push ecx push offset s@ call @_printf add esp,8 ; ; return 0; ; ?live16386@96: ; xor eax,eax ; ; } ; @10: @9: mov esp,ebp pop ebp ret @_main endp _main ends |
Bo Persson <bop@gmb.dk>: Jan 27 12:17PM +0100 On 2015-01-27 09:22, DSF wrote: > Note the missing ampersand on the second Foo of the inline line. > Shouldn't this be an error? The TU compiled with 0 errors and 0 > warnings. That's a different operator that doesn't match the friend declaration. It will compare foo1 against a copy of foo2, but is perfectly legal. > BTW, adding the ampersand did not fix the main problem. Too bad. Bo Persson |
Louis Krupp <lkrupp@nospam.pssw.com.invalid>: Jan 27 07:23AM -0700 On Mon, 26 Jan 2015 16:00:28 -0500, DSF <notavalid@address.here> wrote: > printf("fo1 %s equal fo2\n", result ? "does" : "does not"); > return 0; >} Is it possible that this has nothing to do with templates? Compiling this code with -c seems to reproduce the problem: === class Foo { public: Foo() : num(0){}; int num; }; #if 0 bool operator==(const Foo& f1, const Foo& f2) { return f1.num == f2.num; }
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment