Note that there are some explanatory texts on larger screens.

plurals
  1. POWhen are pad bytes copied - struct assignment, pass by value, other?
    primarykey
    data
    text
    <p>While debugging a problem, the following issue came up. (Please ignore minor code errors; the code is just for illustration.)</p> <p>The following struct is defined:</p> <pre><code>typedef struct box_t { uint32_t x; uint16_t y; } box_t; </code></pre> <p>Instances of this struct are being passed by value from function to function (obviously simplified):</p> <pre><code>void fun_a(box_t b) { ... use b ... } void fun_b(box_t bb) { // pass bb by value int err = funa(bb); } void fun_c(void) { box_t real_b; box_t some_b[10]; ... ... use real_b and some_b[] ... ... funb(real_b); funb(some_b[3]); ... box_t copy_b = some_b[5]; ... } </code></pre> <p>In some cases, two instances of box_t are compared like this:</p> <pre><code> memcmp(bm, bn, sizeof(box_t)); </code></pre> <p>Within several nested calls, the bytes of the box_t arg were dumped using something like this:</p> <pre><code>char *p = (char*) &amp;a_box_t_arg; for (i=0; i &lt; sizeof(box_t); i++) { printf(" %02X", *p &amp; 0xFF); p++; } printf("\n"); </code></pre> <p>The sizeof(box_t) is 8; there are 2 pad bytes (discovered as being after the uint16_t). The dump showed that the fields of the struct were equal, but the pad bytes were not; this caused the memcmp to fail (not surprisingly).</p> <p>The interesting part has been to discover where the 'corrupted' pad values came from. After tracking backwards it was discovered that some of the box_t instances were declared as local variables and were initialized like this:</p> <pre><code>box_t b; b.x = 1; b.y = 2; </code></pre> <p>The above does not (appear to) initialize the pad bytes, which appear to contain 'garbage' (whatever was in the stack space allocated for b). In most cases the initialization was done using <code>memset(b, 0, sizeof(box_t))</code>.</p> <p>The question is whether initializing an instance of box_t by either (1) struct assignment or (2) passing by value will always do the equivalent of a memcpy of sizeof(box_t). Is it ever the case that only the 6 bytes of the 'real fields' are copied (and the pad bytes are not). </p> <p>From the debugging it appears that the memcpy sizeof(box_t) equivalent is always done. Is there anything (e.g., in the standard) that actually specifies this? It would be helpful to know what can be counted on regarding the handling of the pad bytes as debugging goes forward.</p> <p>Thanks! (Using GCC 4.4.3 on Ubuntu LTS 10.4 64-bit)</p> <p>For bonus points:</p> <pre><code>void f(void) { box_t ba; box_t bb; box_t bc; </code></pre> <p>The 3 instances are allocated 16 bytes apart while sizeof() shows 8. Why the extra space?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    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. 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