This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Strict aliasing and malloc


On Tue, Jul 3, 2018 at 8:07 PM, Brian Inglis
<Brian.Inglis@systematicsw.ab.ca> wrote:
> On 2018-07-03 09:16, narwhal x wrote:
>> Hello,
>>
>> I have a question regarding newlib and the -fstrict-aliasing implied
>> by turning on O2.
>>
>> The strict aliasing implied by the ISO standard and enabled in gcc
>> with O2 (This might be specific to gcc, but could be the case with any
>> compiler with aliasing optimizations) makes it so you can only cast a
>> pointer to a compatible type, and a special case is malloc, which
>> should return an "undeclared type" *.
>>
>> I however did not find the -fno-strict-aliasing flag in any
>> configuration or makefile (If I just overlooked it, and the flag is
>> mandatory that would answer my question)
>>
>> My question:
>> In newlib/libc/stdlib/mallocr.c on line 2212 you have the statement:
>> "top = (mchunkptr)brk;"
>> Here top is of type "mchunkptr" and brk is a "char *". The standard
>> says that you can not just alias a incompatible type and dereference
>> it (unless it's a malloc'ed variable, as it would change it's type
>> when written to, but how do you inform the compiler?)
>>
>> As an example, see 4.2.1 (p. 63) in
>> https://www.cl.cam.ac.uk/~pes20/cerberus/notes30.pdf
>>
>> So is this allowed? Or am I missing something.
>>
>> * After asking in the gcc IRC, they mentioned that the way they go
>> about having the special case for malloc is making sure the libc
>> library is linked from a library and no LTO is performed.
>>
>>
>> My main reason for asking is just wanting to know how a malloc
>> implementation should deal with these restrictions stated by the ISO C
>> standard, and improve my understanding of the (sometimes confusing)
>> aliasing rules.
>
> Pointer types char * and void * can be converted to other data pointer types,
> and character types can alias other types, but you should not alias objects via
> casts or conversions of pointers to objects stored as incompatible types,
> because optimization could eliminate the stores, so the underlying storage of
> the object of incompatible type may not be updated, and the compiler would not
> know that because the type is different, as the compiler does not track possible
> aliasing of incompatible types. Roughly IMHO HTH YMMV ;^>
>
> Implementations of malloc use char * internally and convert those to char ** and
> int * to maintain their internal housekeeping data at the start of the block,
> often using unions, returning a pointer to universally aligned storage following
> that block prefix, often resulting in malloc overhead of one or more universally
> aligned blocks per allocation; reducing space overhead takes more work: see e.g.
> https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/mallocr.c;h=ecc445f3d36365a4840e31c737db5018ddba42e9;hb=8e732f7f7f684f22b283f39a5d407375b3b0b3af
> --
> Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada

Forgive me if I misunderstand, but doesn't your recap regarding strict
aliasing agree with my understanding that this is an aliasing
violation?
Because you mention (correctly I think)
> ... you should not alias objects via
> casts or conversions of pointers to objects stored as incompatible types ...

And in the case I mentioned (one of many) in mallocr.c on line 2212
you have the statement:
>> "top = (mchunkptr)brk;"

Here brk is declared as: char *brk and is returned by sbrk (in my
case) which takes memory from the heap declared somewhere in a
linkerscript (or similar) AFAIK. But top is a mchunk *, which is a
struct.
So this is not a compatible type right (so the ARE incompatible)? You
could cast from mchunk * TO char * and dereference it according to the
standard, but not the other way around.
Also if you look at the document I linked in my initial mail
>> As an example, see 4.2.1 (p. 63) in
>> https://www.cl.cam.ac.uk/~pes20/cerberus/notes30.pdf

Isn't this exactly what is done in mallocr.c ? And they state
specifically that this can only be done when strict aliasing is NOT
uphold. And that seems to be in accordance to the standard.
I get that this is how the space is managed internally, I also know a
lot of embedded applications and networking stacks do this casting
from a char * to a struct *, but these also had to disable strict
aliasing to avoid bugs.
So am I missing something? If I am talking nonsense or
misunderstanding something please let me know.
I know it works basically always, but isn't this technically undefined
behavior without -fno-strict-aliasing?

Thanks


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]