SUMM: Unaligned access

From: Guy Dallaire <dallaire_at_total.net>
Date: Thu, 03 Apr 1997 11:03:41

Thanks to all for the FAST response.

Strange thing: You'll discover that someone is gettinmg this kind of errors
when running an app from an NFS mount point when the NFS version between
client and server is not identical. Strange... I wondr what would happen if
the program was moved to a generic UFS or ADVFS file system, or if it still
does not work, be recompiled there. Maybe the physical file layout has
something to do with it (but I would doubt it, it's a binary after all !)

Here is the original post as well as some answers.

Guy, I have a similar problem here. It appears that programs located on an
ADVFS-partition on a DU V4.0 NFS-server, activated from a DU V2.0
NFS-client produce this messages. If the same programs are activated from a
V4.0 NFS-client no messages appear.

Perhaps this gives you a hint.

BTW. If this is exact your situation and you might get a solution for it
please let me know.

-------------

 Hi. Look at "uac" command to disable the printing of such errors. Regards, fb
-- 
 ________________________________________________
| Fabio Bossi - ISIS CEC Ispra (Va) - Italy      |
| Tel: +39 332 789840                            |
| Fax: +39 332 785815                            |
| X.400: g=Fabio;s=Bossi;;p=ccrispra;a=garr;c=it |
|________________________________________________|
--------------------------
  A typical way to obtain this sort of errors (in Fortran) is to have
  n-bit words not aligned on natural boundaries.
  E.g in a COMMON block if you have
      REAL*8 D
      REAL*4 R
      INTEGER*4 J
      INTEGER*2 I
      COMMON /XX/D,R,J,I
  everything is fine, all items are aligned on natural boundaries.
  If instead one declares
      COMMON /XX/I,J,D,R
     
  one has a bad alignment (a 16-bit word followed by a 32-bit word at
  an unnatural boundary, and also the nexg 64-bit word is unaligned)
  The same sort of thing can occur using the EQUIVALENCE statement.
      REAL*8 D
      REAL*4 R(10)
      EQUIVALENCE (D,R(2))
  is unaligned (while D can be equivalenced with R(1) or R(5) or R(9))
  Similar things can occur with record arrangents.
  Most compilers are smart enough to work around this, but at a price
  of slower performance, if many fixups are needed (e.g. in loops).
  
> Is there a way to prevent the appearance of these messages, or better, to
> fix the problem easily ? 
  uac p noprint    suppresses the messages (see man uac)
----------------------------------------------------------------------------
Lucio Chiappetti - IFCTR/CNR - via Bassini 15 - I-20133 Milano (Italy)      
----------------
I don't know about Pro C, but we see this when we  use
#pragma pack(1)
or gcc's  __attribute__ ((packed));
you can get unaligned access errors if you don't align fields in a
structure to their natural boundries.  We use this for network communcation.
Another common souce of these errors can occur when you align the
members by hand properly, but then don't pad out the structure to an
even # of bytes for the first element in the array
#pragma pack(1)
struct foo 
{
	int a;
	char b;
};
#pragma pack(8)
So sizeof (struct foo) == 5.  this is OK for one instance of the
structure, but bad news if you want an array of 2 or more lelements.
foo_ptr = malloc (sizeof (foo) * 2)
accessing foo_ptr[1].a is now going to give unaligned access errors.
---------------------------------------------------------------------------
Another common thing that can happen is when you copy elements into a
(unsigned char *) buffer and cast them to short, int, long, or pointers:
Say someone sends you a 5 byte packet.  The first byte is the length of
a packet, the next 4 bytes are a 4 byte integer:
unsigned char buf[5]
my_int = *(int *)(buf+1)
will give an unaligned access errors.  
memcpy (&my_int, buf+1, sizeof(int));
Will not.
-Eric.
---------------------------------
In modern RISC processors, the address for a memory fetch of a certain size
must be evenly divisible by its size; i.e. a 8-byte floating point number
must be at an address that is a multiple of 8.  An 8-bit char can start at
any address.  If you had code like:
struct test
{
  char   schv_char;
  double sdfv_valu;
};
The compiler must determine the largest size object in the struct, double
thus 8 bytes, ensure that all instances of struct test are stored starting
at an address that is a multiple of 8, and insert 7 bytes of padding
between schv_char and sdfv_valu to ensure sdfv_valu is at an address that
is a multiple of 8.
C normally handles this properly.  Fortran does not.
If you have to assess binary data where the double is not aligned, then use
memcpy:
  unsigned char lcha_data[256];
  double        ldfv_valu     ;
  memcpy ( &ldfv_valu,&lcha_data[123],sizeof ( ldfv_valu ) );
The cure for Fortran common blocks is to either put the largest sized 
variables first or to separate the variables of like size into a separate 
common block.
-------------------------
Hi,
you get these messages when ou're reading/writing an integer or double 
which is not on an 8 byte boundary. eg. 
double *n=0x03;
*n = 1.0
this will result in such a warning.
You can toggle off these messages by the uac command. type man uac  :-)
To debug it, you need the sources and then let uac dump core when it 
encounters such a condition ....
Hopt this helps a bit
--------------------
An unaligned access is bad- it's just that the OS is being nice and
fixing things up for you. Basically, it means that a word-access was not
word-aligned. For instance, on a 64-bit alpha, a 64-bit access to
address 0x1400001b0 is okay, because it's 64-bit aligned, as is
0x1400001b8. A 64-bit access to 0x1400001b4, however, would be
unaligned. This causes an unaligned access exception to be raised, which
is handled by breaking the access into the obvious two 32-bit accesses.
The way to fix this would be to determine where you are performing the
access, and figure out why you are performing this access. The most
common case is ported code which casts a pointer into the middle of a
buffer to a pointer to a long, and dereferences it.
The uac command controls what happens on unaligned access. By default, a
warning is printed, "uac p 0" will turn off the printed warning, though
I don't recommend doing this- your bug is still there. "uac p sigbus"
will cause SIGBUS to be delivered to the process whenever it performs
the unaligned access- this enables the programmer to determine exactly
where the access is occurring, using standard debugging techniques (a la
dbx).
-Jim.Zelenka_at_cs.cmu.edu
----------------------
The following is copied from the archives of this list (I searched on 
unaligned access):
> Here is a summary of the replies to my question (below).
>
> 1- The code needs to be 64-bit clean.
>
> 2- The error messages can be disabled by typing the command
>    "uac p 0"    
>
>    (it works)
>
> 3- Compilation flages like "-align dcommons", for Fortran, and
>    "-migrate", for C, will produce a 64-bit clean executable.
>
>    (it works fine)
"uac p 0" simply turns off the error messages.  It doesn't do anything to 
improve performance.
Guy Dallaire
dallaire_at_total.net
"God only knows if god exists"
Received on Thu Apr 03 1997 - 18:32:00 NZST

This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:36 NZDT