Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #91314

Re: Question

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>

Show all headers | View raw


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


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