Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Yes, <code>__attribute__((packed))</code> is potentially unsafe on some systems. The symptom probably won't show up on an x86, which just makes the problem more insidious; testing on x86 systems won't reveal the problem. (On the x86, misaligned accesses are handled in hardware; if you dereference an <code>int*</code> pointer that points to an odd address, it will be a little slower than if it were properly aligned, but you'll get the correct result.)</p> <p>On some other systems, such as SPARC, attempting to access a misaligned <code>int</code> object causes a bus error, crashing the program.</p> <p>There have also been systems where a misaligned access quietly ignores the low-order bits of the address, causing it to access the wrong chunk of memory.</p> <p>Consider the following program:</p> <pre><code>#include &lt;stdio.h&gt; #include &lt;stddef.h&gt; int main(void) { struct foo { char c; int x; } __attribute__((packed)); struct foo arr[2] = { { 'a', 10 }, {'b', 20 } }; int *p0 = &amp;arr[0].x; int *p1 = &amp;arr[1].x; printf("sizeof(struct foo) = %d\n", (int)sizeof(struct foo)); printf("offsetof(struct foo, c) = %d\n", (int)offsetof(struct foo, c)); printf("offsetof(struct foo, x) = %d\n", (int)offsetof(struct foo, x)); printf("arr[0].x = %d\n", arr[0].x); printf("arr[1].x = %d\n", arr[1].x); printf("p0 = %p\n", (void*)p0); printf("p1 = %p\n", (void*)p1); printf("*p0 = %d\n", *p0); printf("*p1 = %d\n", *p1); return 0; } </code></pre> <p>On x86 Ubuntu with gcc 4.5.2, it produces the following output:</p> <pre><code>sizeof(struct foo) = 5 offsetof(struct foo, c) = 0 offsetof(struct foo, x) = 1 arr[0].x = 10 arr[1].x = 20 p0 = 0xbffc104f p1 = 0xbffc1054 *p0 = 10 *p1 = 20 </code></pre> <p>On SPARC Solaris 9 with gcc 4.5.1, it produces the following:</p> <pre><code>sizeof(struct foo) = 5 offsetof(struct foo, c) = 0 offsetof(struct foo, x) = 1 arr[0].x = 10 arr[1].x = 20 p0 = ffbff317 p1 = ffbff31c Bus error </code></pre> <p>In both cases, the program is compiled with no extra options, just <code>gcc packed.c -o packed</code>.</p> <p>(A program that uses a single struct rather than array doesn't reliably exhibit the problem, since the compiler can allocate the struct on an odd address so the <code>x</code> member is properly aligned. With an array of two <code>struct foo</code> objects, at least one or the other will have a misaligned <code>x</code> member.)</p> <p>(In this case, <code>p0</code> points to a misaligned address, because it points to a packed <code>int</code> member following a <code>char</code> member. <code>p1</code> happens to be correctly aligned, since it points to the same member in the second element of the array, so there are two <code>char</code> objects preceding it -- and on SPARC Solaris the array <code>arr</code> appears to be allocated at an address that is even, but not a multiple of 4.)</p> <p>When referring to the member <code>x</code> of a <code>struct foo</code> by name, the compiler knows that <code>x</code> is potentially misaligned, and will generate additional code to access it correctly.</p> <p>Once the address of <code>arr[0].x</code> or <code>arr[1].x</code> has been stored in a pointer object, neither the compiler nor the running program knows that it points to a misaligned <code>int</code> object. It just assumes that it's properly aligned, resulting (on some systems) in a bus error or similar other failure.</p> <p>Fixing this in gcc would, I believe, be impractical. A general solution would require, for each attempt to dereference a pointer to any type with non-trivial alignment requirements either (a) proving at compile time that the pointer doesn't point to a misaligned member of a packed struct, or (b) generating bulkier and slower code that can handle either aligned or misaligned objects.</p> <p>I've submitted a <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51628" rel="noreferrer">gcc bug report</a>. As I said, I don't believe it's practical to fix it, but the documentation should mention it (it currently doesn't).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload