whacko__Cracko
whacko__Cracko

Reputation: 71

segfault giving headache

What is the problem with the following code now?

int main(){
union { 
        char arr[10];  
        int var;  
      } u;  
int *ptr_var= (int*) &(u.arr[1]);  
*ptr_var = 42; 
}

Upvotes: 0

Views: 149

Answers (4)

Alex Y.
Alex Y.

Reputation: 1

This is architecture dependent. I would guess the standard may again say the behavior is "undefined". I am getting different results when running it on different platforms:

1> Linux on X86: runs fine without a problem 2> Solaris on sparc: "Bus error (core dumped)".

Upvotes: 0

DrBeco
DrBeco

Reputation: 11785

This is compiling nice and easy here. No segmentation fault. What is exactly the output of your compiler?

Here you can see:

#include <stdio.h>

int main()
{
    int *ptr_var;
    union
    { 
        char arr[10];  
        int var;  
    } u;  

    u.arr[0]='A';
    u.arr[9]='\0';
    ptr_var = (int*) &u.arr[1];

    *ptr_var = 0x2a;

    printf("%s\n", u.arr);
    printf("%d(d)=%x(x)\n",u.var, u.var);
}

And the answer is:

cpp/test/temp$ gcc union.c -o union
cpp/test/temp$ ./union 
A*
10817(d)=2a41(x)
cpp/test/temp$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

It is a fine way to move bits around. Maybe your segfault is in another area of the program. See this test:

*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);

ptr_var = (int*) &u.arr[1];
*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);

ptr_var = (int*) &u.arr[2];
*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);

And you get:

16(d)=10(x)
4112(d)=1010(x)
1052688(d)=101010(x)

Take care, Beco.

Upvotes: 1

Lindydancer
Lindydancer

Reputation: 26144

Note: a correct answer has already been given, this is simply another way to explain the background.

When accessing objects in memory, most machines require that the objects are aligned. This mean that a four-byte (32 bit) object must be placed on an address that is dividable by four. This originates in the fact that the CPU is connected with the memory using a data-bus, in our example the bus is 32 bits. If the CPU would be to support unaligned accesses, it would have to request two accesses to the memory and puzzle them together. Instead, most architectures consider this an illegal operation.

In your case, you start with a union, which is stored at an even four-byte address. Then you step one byte forward and try to access an int at an address that is must definitely not an even multiple of the size.

Upvotes: 4

Prasoon Saurav
Prasoon Saurav

Reputation: 92884

Are you sure this is giving segfault? The title is misleading!!

AFAIK on older architecture this would result in bus error. But as this post explains you don't get to see bus error these days.

This would cause bus-error because the array/int union ensures that character array arr is also at a reasonably aligned address for an integer that &arr[1] is definitely not aligned properly for the integer. And then you try to store sizeof(int) bytes into an address that is aligned only for single-byte access. Arghh!!!


Upvotes: 3

Related Questions