Liste des Groupes | Revenir à cl c |
On 7/18/2024 2:46 AM, David Brown wrote:It's very easy to make high performance code if correctness doesn't matter! Obviously, correctness is more important.On 17/07/2024 19:53, BGB wrote:My compiler and my Quake 3 port, but most of the bugs in the Quake 3 port thus far were due to bugs either in my compiler or in the runtime libraries.On 7/17/2024 6:38 AM, Bart wrote:>On 13/07/2024 10:39, BGB wrote:>
>But, as I see it, no real point in arguing this stuff (personally, I have better stuff to be doing...).>
We all do. But this group seems to be about arguing about pointless stuff and you might come here when you want a respite from proper work.
>
However (here I assume you've gone back to Quake but that other interested parties might be reading this), consider the program below.
>
I got back to debugging...
To be clear - you are talking about debugging your compiler here, yes?
>
The "magical auto dereferencing pointers" interpretation gives better performance, when it works. In this case, it didn't work...>>
Ironically, one of the big bugs I ended up finding was related to internal struct handling "leaking through" and negatively effecting stuff.
>
say:
typedef struct foo_s foo_t; // don't care what it contains for now.
>
foo_t arr[...];
foo_t temp;
int i, j;
...
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
>
Internally, it would load a reference to arr[i] into temp, but then this location would get overwritten before the third assignment happened, causing the incorrect contents to be copied to arr[j].
>
For now, have ended up changing stuff such that any struct-assignment (for structs in the "by-ref" category) to a local variable will instead copy the contents to the memory location associated with that struct.
How could it possibly mean anything else? Structs in C are objects - contiguous blocks of bytes interpreted by a type. Assigning them will mean copying those bytes. Pretending the language sometimes means structs and sometimes means magical auto-dereferencing pointers to structs is simply wrong.
>
Sadly, there is no good way at the moment to know whether or not it will work, for now forcing the slower and more conservative option.I would think the simple test is that for data that is never changed (or not changed within the function), you can use a constant reference - otherwise you cannot. It is not by coincidence that in C++, it is common to use pass by /const/ reference as an efficient alternative to pass by value for big objects.
The normal system is that local objects are data on the stack - regardless of the size or type, scaler or aggregate. Parameter passing is done by register for some types (for the first few parameters), or the stack otherwise. Returns are in a register or two for some times, or by a stack slot assigned by the caller. For struct parameters or return values, it can be efficient for the caller to pass hidden pointers, but that's not strictly necessary if you have a fixed stack frame layout. (Struct parameters still get copied to the stack to ensure value semantics - the hidden pointer points to the stack copy.)If "foo_t" is 2000 bytes long, then "foo_t temp" makes a 2000 byte space in your local variables (the stack, on virtually every platform) and "temp = arr[i];" does a 2000 byte memcpy(). The same thing applies if "foo_t" is 2 bytes long, or 2 megabytes long. And if there is a stack overflow making "temp", that's the programmer's problem.For now:
>
1 - 16 bytes, goes in registers, except when accessing a member where it needs to be in-memory; unless it is a SIMD type which is special and allows accessing members with the value still in registers.
17 bytes to 15.999K: Accessed by an implicit reference, uses hidden copying to mimic by-value semantics (not quite foolproof as of yet it seems).
16K and beyond, quietly turned into a heap allocation (with a compiler warning). Should otherwise look the same as the prior case.
A rarely used, unreliable feature with unexpected effects and costs is not likely to be a good idea. People are happy to use compilers that don't have this kind of dynamic memory allocation for big local variables - but no one is going to be happy to use a compiler that doesn't accurately support the C semantics for copying structs.And it is only when the direct translation is working properly that you can start to think of improving user convenience. Perhaps you could allocate large temporary objects in non-stack memory somewhere to avoid stack overflows. I don't think that is a good idea, but it's a possibility. Giving compiler warnings about large stack objects is a much better solution IMHO.It both warns and also turns it into a heap allocation.
>
Because warning and the code still working, is better than warning and the program most likely crashing due to a stack overflow (and in cases with no memory protection, probably overwriting a bunch of other stuff in the process).
Les messages affichés proviennent d'usenet.