RFR(S): 8216426: Usage of array placement new may lead to memory corruption
Erik Österlund
erik.osterlund at oracle.com
Tue Jan 15 14:36:59 UTC 2019
Hi Martin,
On 2019-01-15 15:01, Doerr, Martin wrote:
> Hi Roman and Erik,
>
> I don't have GCC 8 so I can't test it. But hotspot heavily uses memset (also with NEW_C_HEAP_ARRAY), so why should it be a problem here?
>
> I don't understand why Bucket is not a POD. Its binary form should look like a C structure.
> And even if it's not POD, why should it yield undefined behavior? We're not using default initialization.
It's not a POD because the standard says it is not. It is explicit about
how you can't have private or protected member variables. Its binary
form should indeed look like a C structure, but it's not a POD. That
implies for example that it will be sent through the stack, not by
register in the calling convention, unlike a POD which is sent by
register. So despite the rules for what is and what is not a POD
seemingly making no sense, they can't just change it to make sense
without breaking the ABI. So I guess we are kind of stuck with it. C++11
and later has improved the situation in this area, but we don't have it.
Unfortunately, the life cycle for non-PODs is coupled with calling
constructors and destructors (unless trivially destructible, then you
don't have to), while the life cycle of PODs is not; it's more like a C
struct. That means that by making that member private, it is not a POD
according to the definition, and suddenly you are not allowed to just
memset it and gotta explicitly construct the object to be compliant with
the standard.
> I believe C++ does not require NULL to be 0 before C++11.
It has to be a constant rvalue expression that evaluates to zero in C++03.
> So memset to 0 may yield undefined behavior, but we rely on this at so many places ...
Well, we are swimming in a vast ocean of undefined behaviour. It's hard
not to, when the standard has made it as hard and unintuitive as
possible to be compliant, and no sensible tools enforcing it.
Thanks,
/Erik
> Best regards,
> Martin
>
>
> -----Original Message-----
> From: Roman Kennke <rkennke at redhat.com>
> Sent: Dienstag, 15. Januar 2019 14:36
> To: Erik Österlund <erik.osterlund at oracle.com>; Doerr, Martin <martin.doerr at sap.com>; Robbin Ehn <robbin.ehn at oracle.com>; hotspot-runtime-dev at openjdk.java.net; Kim Barrett <kim.barrett at oracle.com>; David Holmes (david.holmes at oracle.com) <david.holmes at oracle.com>
> Subject: Re: RFR(S): 8216426: Usage of array placement new may lead to memory corruption
>
> Doesn't using memset mean that newer GCC (8) warns about it and thus
> break compilation? That was the whole point of introducing placement new
> operator to begin with, IIRC.
>
> Roman
>
>> Hi Martin,
>>
>> Unfortunately, according to the C++03 standard, that field needs to be
>> public for the class to be a POD. And if it is not a POD, we will have
>> undefined behaviour. Yay for C++.
>>
>> Thanks,
>> /Erik
>>
>> On 2019-01-15 11:51, Doerr, Martin wrote:
>>> Hi Robbin,
>>>
>>> that's fine. I like it simple.
>>> Version which uses memset and removed constructor:
>>> http://cr.openjdk.java.net/~mdoerr/8216426_array_placement_new/webrev.01/
>>>
>>> I don't like making the field public because it can easily get used
>>> incorrectly because there are bits encoded into the pointer.
>>> So I think we should better not provide direct access to it.
>>>
>>> Best regards,
>>> Martin
>>>
>>>
>>> -----Original Message-----
>>> From: Robbin Ehn <robbin.ehn at oracle.com>
>>> Sent: Dienstag, 15. Januar 2019 10:26
>>> To: Erik Österlund <erik.osterlund at oracle.com>; Doerr, Martin
>>> <martin.doerr at sap.com>; hotspot-runtime-dev at openjdk.java.net; Kim
>>> Barrett <kim.barrett at oracle.com>; David Holmes
>>> (david.holmes at oracle.com) <david.holmes at oracle.com>
>>> Subject: Re: RFR(S): 8216426: Usage of array placement new may lead to
>>> memory corruption
>>>
>>> On 2019-01-15 10:15, Erik Österlund wrote:
>>>> Hi,
>>>>
>>>> Perhaps an alternative approach is to make the Bucket a POD (make the
>>>> private member public, and remove the
>>>> constructor), and then simply memset the memory to zero.
>>> Sorry, we have NMT tracking via NEW_C_HEAP_ARRAY(Bucket, _size, F);.
>>> So yes, make it a POD and use memset.
>>>
>>> /Robbin
>>>
>>>> Thanks,
>>>> /Erik
>>>>
>>>> On 2019-01-15 09:03, Robbin Ehn wrote:
>>>>> Hi Martin,
>>>>>
>>>>> The Bucket should extend CHeapObj<F>, now that it could.
>>>>> Otherwise looks good, thanks.
>>>>>
>>>>> Originally Bucket did this and I used memset, but gdb was very upset
>>>>> by this.
>>>>> So I changed to array placement new, which meant I had to remove
>>>>> CHeapObj<F> if I remember correctly :)
>>>>>
>>>>> /Robbin
>>>>>
>>>>> On 2019-01-14 17:39, Doerr, Martin wrote:
>>>>>> Hi,
>>>>>>
>>>>>> thanks for looking at this issue and especially for adding comments.
>>>>>> Sounds like this issue should better get fixed although there are
>>>>>> no known problems.
>>>>>>
>>>>>> Should we fix it by replacing the array placement new by normal
>>>>>> placement new for each element?
>>>>>> http://cr.openjdk.java.net/~mdoerr/8216426_array_placement_new/webrev.00/
>>>>>>
>>>>>>
>>>>>> Best regards,
>>>>>> Martin
>>>>>>
More information about the hotspot-runtime-dev
mailing list