Deutsch   English   Français   Italiano  
<v7b2i5$2dtpm$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!news.nobody.at!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: David Brown <david.brown@hesbynett.no>
Newsgroups: comp.lang.c
Subject: =?UTF-8?Q?Re=3a_technology_discussion_=e2=86=92_does_the_world_need?=
 =?UTF-8?B?IGEgIm5ldyIgQyA/?=
Date: Thu, 18 Jul 2024 14:41:40 +0200
Organization: A noiseless patient Spider
Lines: 148
Message-ID: <v7b2i5$2dtpm$1@dont-email.me>
References: <v66eci$2qeee$1@dont-email.me> <v6jiud$1dsjb$1@dont-email.me>
 <877cdur1z9.fsf@bsb.me.uk> <v6joi4$1epoj$1@dont-email.me>
 <871q42qy33.fsf@bsb.me.uk> <v6k6i0$1h4d3$1@dont-email.me>
 <87ed82p28y.fsf@bsb.me.uk> <v6m03l$1tf05$1@dont-email.me>
 <87r0c1nzjj.fsf@bsb.me.uk> <v6m716$1urj4$1@dont-email.me>
 <87ikxconq4.fsf@bsb.me.uk> <v6n8iu$24af0$1@dont-email.me>
 <20240711115418.00001cdf@yahoo.com> <v6oamt$2d8nn$1@dont-email.me>
 <v6oct4$2djgq$2@dont-email.me> <v6of96$2ekb0$1@dont-email.me>
 <v6ovfc$2hcpf$1@dont-email.me> <v6p4hf$2icph$1@dont-email.me>
 <v6qgpu$2t6p7$3@dont-email.me> <v6r33m$30grj$1@dont-email.me>
 <20240712154252.00005c2f@yahoo.com> <86o7717jj1.fsf@linuxsc.com>
 <v6ti10$3gru4$1@dont-email.me> <v78af7$1qkuf$1@dont-email.me>
 <v790f2$1up8s$1@dont-email.me> <v7ah7p$2ak85$1@dont-email.me>
 <v7apdt$2c6vd$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Thu, 18 Jul 2024 14:41:42 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="5e58e10ba9a4731c305671ca05dd8458";
	logging-data="2553654"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX19EYRyPw894zkLxsPNcDhyyCpx7yWjXgb4="
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101
 Thunderbird/102.11.0
Cancel-Lock: sha1:KH0Aul2VcrAc30uLI+YdQPXn62Q=
Content-Language: en-GB
In-Reply-To: <v7apdt$2c6vd$1@dont-email.me>
Bytes: 8542

On 18/07/2024 12:05, BGB wrote:
> On 7/18/2024 2:46 AM, David Brown wrote:
>> On 17/07/2024 19:53, BGB wrote:
>>> 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?
>>
> 
> 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.
> 
> 
>>>
>>> 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.
>>
> 
> The "magical auto dereferencing pointers" interpretation gives better 
> performance, when it works. In this case, it didn't work...

It's very easy to make high performance code if correctness doesn't 
matter!  Obviously, correctness is more important.

> 
> 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.

> 
> 
>> 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.
> 

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.)

Trying to have special cases for different sizes, or to eliminate extra 
copies of structs by having pointers and hoping nothing gets changed, is 
just extra complication with a high risk and low gains.  If the 
programmer knows the structs are big and it is better to put them on the 
heap, or to pass around references, then let the /programmer/ do that. 
We are talking about /C/ here - programmers are expected to take 
responsibility for doing this stuff manually.  It is not a high-level 
hand-holding automated language.  If a programmer passes a struct by 
value, it is because they know it is small enough to do so efficiently, 
or because they know the caller might find it convenient to modify a 
local copy and don't want the caller's copy affected.  If they know it 
is safe to pass a pointer, they will use a (possibly const) pointer to 
the struct as the parameter.

You are trying to be too smart here, IMHO - the compiler's job is to let 
the programmer be smart.  It's always nice to have optimisations, but 
not at the expense of correctness.

> 
> 
>> 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).

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.