Visual C++ Equivalent of Gcc'S _Attribute_ ((_Packed_))

Visual C++ equivalent of GCC's __attribute__ ((__packed__))

You can define PACK like as follows for GNU GCC and MSVC:

#ifdef __GNUC__
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#endif

#ifdef _MSC_VER
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
#endif

And use it like this:

PACK(struct myStruct
{
int a;
int b;
});

A __attribute__((packed)) like attribute not GCC Specific

There is no standard approach to accomplish what __attribute__((packed)) does. The typical solution is to use #ifdef's to handle different compilers. You can find a few solutions to this approach at this SO post which also contains the details on the Visual C++ equivalent of __attribute__((packed)). Alternatively, GCC supports the Windows struct packing pragmas, so if you are just concerned with Windows and GCC you could just use the Windows approach.

Is gcc's __attribute__((packed)) / #pragma pack unsafe?

Yes, __attribute__((packed)) 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 int* 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.)

On some other systems, such as SPARC, attempting to access a misaligned int object causes a bus error, crashing the program.

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.

Consider the following program:

#include <stdio.h>
#include <stddef.h>
int main(void)
{
struct foo {
char c;
int x;
} __attribute__((packed));
struct foo arr[2] = { { 'a', 10 }, {'b', 20 } };
int *p0 = &arr[0].x;
int *p1 = &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;
}

On x86 Ubuntu with gcc 4.5.2, it produces the following output:

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

On SPARC Solaris 9 with gcc 4.5.1, it produces the following:

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

In both cases, the program is compiled with no extra options, just gcc packed.c -o packed.

(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 x member is properly aligned. With an array of two struct foo objects, at least one or the other will have a misaligned x member.)

(In this case, p0 points to a misaligned address, because it points to a packed int member following a char member. p1 happens to be correctly aligned, since it points to the same member in the second element of the array, so there are two char objects preceding it -- and on SPARC Solaris the array arr appears to be allocated at an address that is even, but not a multiple of 4.)

When referring to the member x of a struct foo by name, the compiler knows that x is potentially misaligned, and will generate additional code to access it correctly.

Once the address of arr[0].x or arr[1].x has been stored in a pointer object, neither the compiler nor the running program knows that it points to a misaligned int object. It just assumes that it's properly aligned, resulting (on some systems) in a bus error or similar other failure.

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.

I've submitted a gcc bug report. As I said, I don't believe it's practical to fix it, but the documentation should mention it (it currently doesn't).

UPDATE: As of 2018-12-20, this bug is marked as FIXED. The patch will appear in gcc 9 with the addition of a new -Waddress-of-packed-member option, enabled by default.

When address of packed member of struct or union is taken, it may
result in an unaligned pointer value. This patch adds
-Waddress-of-packed-member to check alignment at pointer assignment and warn unaligned address as well as unaligned pointer

I've just built that version of gcc from source. For the above program, it produces these diagnostics:

c.c: In function ‘main’:
c.c:10:15: warning: taking address of packed member of ‘struct foo’ may result in an unaligned pointer value [-Waddress-of-packed-member]
10 | int *p0 = &arr[0].x;
| ^~~~~~~~~
c.c:11:15: warning: taking address of packed member of ‘struct foo’ may result in an unaligned pointer value [-Waddress-of-packed-member]
11 | int *p1 = &arr[1].x;
| ^~~~~~~~~

how to translate struct packing from vc++ to gcc

You can add attribute((packed)) to individual data items to achieve this. In this case the packing is applied for a data item, so no need to restore the old mode.

Ex :
For Structures :

typedef struct _MY_STRUCT
{

}__attribute__((packed)) MY_STRUCT;

For data members :

struct MyStruct {

char c;

int myInt1 __attribute__ ((packed));

char b;

int myInt2 __attribute__ ((packed));

};

Does GCC's __attribute__((__packed__)) retain the original ordering?

Assuming that you are asking whether the struct members will retain the order specified in their definition, the answer is yes. The Standard requires that successive members have increasing addresses:

Section §6.7.2.1p13:

Within a
structure object, the non-bit-field
members and the units in which
bit-fields reside have addresses that
increase in the order in which they
are declared.

and the documentation for the packed attribute clearly states that only padding/alignment is affected:

The packed attribute specifies that a
variable or structure field should
have the smallest possible
alignment—one byte for a variable, and
one bit for a field, unless you
specify a larger value with the
aligned attribute.

Portable equivalent to gcc's __attribute__(cleanup)

There's no portable way in C.

Fortunately it's a standard feature of C++ with destructors.

Edit:

MSVC appears to have __try and __finally keywords which can be used for this purpose as well. This is different than the C++ exception handling and I think it's available in C.

I think you'll find that cleanup and try/finally aren't widely used specifically because of the implicit support in C++, which is "close enough" to C that people interested in the behavior can switch their code to C++ with ease.

Is there a portable equivalent of gcc's __attribute__ (pure)?

Since C++11, you can use the standardized attribute syntax with GCC specific attributes:

[[gnu::pure]]
int foo(int)

Since C++17, this is guaranteed to be fine on any compiler, since if they don't recognize [[gnu::pure]], they must ignore it without error.

MSVC equivalent of __attribute__ ((warn_unused_result))?

It's _Check_return_. See here for examples of similar annotations and here for function behaviour. It's supported since MSVC 2012.

Example:

_Check_return_
int my_return_must_be_checked() {
return 42;
}


Related Topics



Leave a reply



Submit