Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
| From | DFS <nospam@dfs.com> |
|---|---|
| Newsgroups | comp.lang.c |
| Subject | Re: Question |
| Date | 2016-07-29 10:14 -0400 |
| Organization | A noiseless patient Spider |
| Message-ID | <nnfobq$ees$3@dont-email.me> (permalink) |
| References | <nnd8ue$nnp$2@dont-email.me> <nndoie$ip1$1@dont-email.me> |
On 7/28/2016 4:05 PM, James Kuyper wrote:
> On 07/28/2016 11:38 AM, DFS wrote:
>> Take a C structure:
>>
>> struct imageType {
>> imageOpsType *ops;
>> coordType width;
>> coordType height;
>> int32_t depth; /* 1..32 */
>> int32_t linebytes; /* bytes per line */
>> int32_t allocated; /* bytes allocated */
>> int64_t fill; /* color to fill with */
>> int8_t sign;
>> imageType *primary; /* for secondary, assoc primary */
>> coordType primaryX; /* for secondary, offset in primary */
>> coordType primaryY; /* for secondary, offset in primary */
>> int8_t *data;
>> uint32_t flags; /* image access mode(s) */
>> int32_t verbose;
>> int32_t page; /* number of the current page */
>> double resX; /* pixels per unit in X */
>> double resY; /* pixels per unit in Y */
>> int32_t resUnit; /* 0=nores 1=unk 2=inch 3=cm */
>> char modes[MAX_MODES]; /* modes used with open */
>> char name[MAX_NAME];
>> int64_t clientData[CLIENT_SIZE]; };
>>
>>
>> What does the following statement accomplish, given that
>> "image" and "src" are both pointers to imageType?
>
> Assuming:
> typedef struct imageType imageType;
> imageType *image;
> imageType *src;
>
> Then the following code:
>
>> (*(imageType**)&(image)->clientData[0])=(src)
>
> takes image, and finds the clientData element in the struct that it
> points at, and then locates the first element of that array. Then it
> takes the address of that element, and converts the resulting pointer to
> be imageType**. then it dereferences that pointer, and stores the value
> of src into the location that it points at.
>
> Here's the key problem: the conversion from int64_t* to imageType** is
> covered only by 6.3.2.3p7: "If the resulting pointer is not correctly
> aligned68) for the referenced type, the behavior is undefined.
> Otherwise, when converted back again, the result shall compare equal to
> the original pointer."
>
> The first key point: the standard gives no guarantee that int64_t is
> correctly aligned to hold an imageType*. It's fairly likely that it will
> be correctly aligned, but portable code shouldn't make the assumption
> that this code had defined behavior
> In C2011, you could force clientData to have the correct alignment, by
> adding _Alignas(struct imageType*) to the declaration of clientData. In
> previous versions of C, the only way to guarantee that it was correctly
> aligned was to put it into a union with an imageType*.
>
> The second key point is hard to notice: the standard never specifies
> where the resulting pointer points. If the alignment is not a problem,
> most people just assume that the resulting pointer points at memory
> starting in the same location as clientData. People make such
> assumptions because that's the way it's almost always implemented - but
> the standard makes no such guarantee.
>
> The third key point is that the only operation that the standard
> guarantees to be permitted on the resulting pointer value is conversion
> back to its original type. Using it in any other way (for instance, by
> dereferencing it) has behavior which is undefined by reason of a lack of
> a definition.
>
> The fourth key point is that if you are correct in your assumption that
> it still points at the same location in memory as the original pointer,
> then this code tries to access memory which has an effective type of
> int64_t, using an lvalue with the type imageType*. That is not one of
> the cases permitted by the anti-aliasing rule, 6.5p7 (unless int64_t is
> a character type, which is technically possible, but extremely
> unlikely), so the behavior is undefined.
> You should understand the purpose of this rule: if another piece of code
> refers to image->clientData[i], the compiler is NOT required to notice
> that, for i=0, this expression refers to the same piece of memory as the
> other expression, since they have two unrelated types. Reading and
> writing through lvalues of one type need not be kept synchronized with
> reads and writes through the other. It could keep one stored in a
> register, while writing the other to memory. The net result is
> unpredictable.
>
> The Fifth point is that there's no guarantee that clientData will be big
> enough to store the imageType* object. With int64_t, that's extremely
> unlikely to happen, particularly if CLIENT_SIZE is big enough. However,
> this kind of type punning is extremely popular, and it's not unusual in
> other cases for someone to forget to make the target object big enough.
>
> Any one of those issues would be sufficient to make me choose an
> alternative way of handling this - and there is one. Just make
> clientData a union of all the different types that client data might
> come in (which could be problematic, if that list is large).
> Alternatively, use memcpy() to load the representation of one type into
> memory with a different type. Either of those approaches would avoid
> every single issue I raised above.
>
> However, most of the issues I've raised above are unlikely to come up in
> practice, which is why type-punning like this is relatively popular. The
> 'where does it point" issue is the one least likely to be a problem. The
> anti-aliasing rule, however, has a significant chance of causing
> problems for real-world code using real-world compilers.
Thanks for the excellent, detailed reply.
Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Question DFS <nospam@dfs.com> - 2016-07-28 11:38 -0400
Re: Question Melzzzzz <mel@zzzzz.com> - 2016-07-28 17:50 +0200
Re: Question BartC <bc@freeuk.com> - 2016-07-28 17:49 +0100
Re: Question Melzzzzz <mel@zzzzz.com> - 2016-07-28 18:52 +0200
Re: Question Keith Thompson <kst-u@mib.org> - 2016-07-28 11:58 -0700
Re: Question BartC <bc@freeuk.com> - 2016-07-28 20:57 +0100
Re: Question "D. Aaron Sawyer" <aaron@110.net> - 2016-07-28 13:55 -0300
Re: Question Barry Schwarz <schwarzb@dqel.com> - 2016-07-28 11:38 -0700
Re: Question DFS <nospam@dfs.com> - 2016-07-28 15:20 -0400
Re: Question Tim Rentsch <txr@alumni.caltech.edu> - 2016-07-30 09:24 -0700
Re: Question Ian Collins <ian-news@hotmail.com> - 2016-07-29 07:23 +1200
Re: Question James Kuyper <jameskuyper@verizon.net> - 2016-07-28 16:05 -0400
Re: Question DFS <nospam@dfs.com> - 2016-07-29 10:14 -0400
Re: Question "James R. Kuyper" <jameskuyper@verizon.net> - 2016-07-30 14:45 -0400
Re: Question supercat@casperkitty.com - 2016-08-01 05:19 -0700
Re: Question Tim Rentsch <txr@alumni.caltech.edu> - 2016-07-30 09:17 -0700
csiph-web