T
Travis Vitek
I'm maintaining some code that uses the SunOS priocntl system call
[*], and this has led me to some questions about type punning. To
avoid a long-winded explaination, I'm just going to post some source
and then ask my questions.
#define PC_CLNMSZ 16
#define PC_CLINFOSZ (32 / sizeof (int))
// The pc_clinfo member is used to return data describing the
// attributes of a specific class. The format of this data is
// class-specific and is described under the appropriate
// heading.
typedef struct pcinfo
{
int pc_cid; /* class id */
char pc_clname[PC_CLNMSZ]; /* class name */
int pc_clinfo[PC_CLINFOSZ]; /* class information */
} pcinfo_t;
// realtime class attributes in the pc_clinfo buffer are in
// this format.
typedef struct rtinfo
{
short rt_maxpri;
} rtinfo_t;
int main ()
{
pcinfo_t pc;
// assume a call to priocntl() will initialize pc with
// something like this...
// pc.pc_clname [0] = 'R';
// pc.pc_clname [1] = 'T';
// pc.pc_clname [2] = 0;
//if (-1L == priocntl (idtype_t(), id_t(), PC_GETCLINFO, &pc))
// return -1;
//
rtinfo_t* prt = (rtinfo_t*)pc.pc_clinfo;
return 0 == prt->rt_maxpri;
}
The gcc-4.1.1 compiler generates the following warning when casting
pc.pc_clinfo (an array of int) to rtinfo_t*.
t.cpp: In function 'int main()':
t.cpp:38: warning: dereferencing type-punned pointer will break
strict-aliasing rules
It is clear that we are type-punning the pointer, but I do not see how
this particular case is dangerous. While some of these questions may
be more appropriate on the gcc list, I'm hoping to better understand
how this is supposed to work, not how it happens to work on one
implementation. My questions are as follows...
1. is this actually a bogus warning?
2. is this a dangerous thing to do?
2. why does changing pc_clinfo to array of char eliminate the
warning? i.e., does that make the cast 'safe'?
3. what techniques are there for avoiding problems like this?
If my understanding of the standard is correct, the above does indeed
invoke undefined behavior, but I'm not certain how exactly to best
work around the issue and to avoid dangerous punning in the future.
Travis
[*] http://docs.sun.com/app/docs/doc/816-5167/priocntl-2
[*], and this has led me to some questions about type punning. To
avoid a long-winded explaination, I'm just going to post some source
and then ask my questions.
#define PC_CLNMSZ 16
#define PC_CLINFOSZ (32 / sizeof (int))
// The pc_clinfo member is used to return data describing the
// attributes of a specific class. The format of this data is
// class-specific and is described under the appropriate
// heading.
typedef struct pcinfo
{
int pc_cid; /* class id */
char pc_clname[PC_CLNMSZ]; /* class name */
int pc_clinfo[PC_CLINFOSZ]; /* class information */
} pcinfo_t;
// realtime class attributes in the pc_clinfo buffer are in
// this format.
typedef struct rtinfo
{
short rt_maxpri;
} rtinfo_t;
int main ()
{
pcinfo_t pc;
// assume a call to priocntl() will initialize pc with
// something like this...
// pc.pc_clname [0] = 'R';
// pc.pc_clname [1] = 'T';
// pc.pc_clname [2] = 0;
//if (-1L == priocntl (idtype_t(), id_t(), PC_GETCLINFO, &pc))
// return -1;
//
rtinfo_t* prt = (rtinfo_t*)pc.pc_clinfo;
return 0 == prt->rt_maxpri;
}
The gcc-4.1.1 compiler generates the following warning when casting
pc.pc_clinfo (an array of int) to rtinfo_t*.
t.cpp: In function 'int main()':
t.cpp:38: warning: dereferencing type-punned pointer will break
strict-aliasing rules
It is clear that we are type-punning the pointer, but I do not see how
this particular case is dangerous. While some of these questions may
be more appropriate on the gcc list, I'm hoping to better understand
how this is supposed to work, not how it happens to work on one
implementation. My questions are as follows...
1. is this actually a bogus warning?
2. is this a dangerous thing to do?
2. why does changing pc_clinfo to array of char eliminate the
warning? i.e., does that make the cast 'safe'?
3. what techniques are there for avoiding problems like this?
If my understanding of the standard is correct, the above does indeed
invoke undefined behavior, but I'm not certain how exactly to best
work around the issue and to avoid dangerous punning in the future.
Travis
[*] http://docs.sun.com/app/docs/doc/816-5167/priocntl-2