What is happening with the sizeof this struct? [duplicate] - c

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 6 years ago.
I was looking into structs in C when I noticed this oddity.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
struct vulnStruct {
char start[20];
char overflow[10];
char *controlledPointer;
};
int main(int argc, char *argv[]){
struct vulnStruct *test = malloc(sizeof(struct vulnStruct));
printf("Sizeof vulnStruct: %d\r\n", sizeof(struct vulnStruct));
printf("Sizeof start: %d\r\n", sizeof(test->start));
printf("Sizeof overflow: %d\r\n", sizeof(test->overflow));
printf("Sizeof controlledPointer: %d\n\r", sizeof(test->controlledPointer));
free(test);
return 0;
}
When compiled this program should output the sizeof the vulnStruct and its elements. Manually adding up the struct shows that it should be 38 bytes long however when this program is run it shows that the struct's size is instead 40 bytes long. At first I thought it was just padding for the struct as answered here (Size of a structure in C) however, when I add a 2 byte field (uint16_t) to the end of the struct in an attempt to fill the padding it just increases the struct by 2 bytes. Is this because the controlledPointer is being padded to 10 bytes by the compiler and won't let anything else use that space or is there something like a canary at the end that is taking up the space. If it is just padding is there anyway to arrange the elements so that the padding can be used by another field?
EDIT:
It would probably help if I get the output of the program as well
Sizeof vulnStruct: 40
Sizeof start: 20
Sizeof overflow: 10
Sizeof controlledPointer: 8
Thanks in advance!

The padding is between overflow[10]; and *controlledPointer.
The problem is that it's doing 4-byte alignment of the fields--something that almost always is worthwhile to do. Two bytes of memory is almost always cheaper than the time penalty for a non-aligned memory access.
The only cases where this would be an issue is if you're trying to match some other structure or when you have a huge number of items. Declare it accordingly in these cases. My C is too rusty to tell you how to declare it, though.

The problem with structures is that they have "padding" meaning that if you have 1 char in a structure the structure will MOST PROBABLY have a size of 4bytes/8bytes depending on the data bus of your processor. This is due to the fact that to optimize the access speed, when compiling the structure is padded with 0xff bytes.
There is some compilation directives which don't use padding but this is not recommended UNLESS you are programming an actual device. This can be done in gcc(the default unix compile) with the following directive but it depends on each compiler:
#pragma (push,pack 1)
//define structure(...)
#pragma (pop)
The pragma in this case has it's own stack, look at this post if you want a clearer idea on padding and the pragma directive

Note that your results will very much vary per target/compiler.
Here's what I get when I try to find out more about padding specifically:
$ clang -Wpadded -Wno-format padd.c
padd.c:10:11: warning: padding struct 'struct vulnStruct' with 2 bytes to align 'controlledPointer' [-Wpadded]
char *controlledPointer;
^
1 warning generated.
This explains which field was aligned and for what reasons.

Your controlledPointer needs to start at an address that is a multiple of 8.
struct vulnStruct {
char start[20];
char overflow[10]; // 30 bytes
// 30 is not a multiple of 8.
// 2 bytes padding here
// now controlledPointer starts at an address that is a multiple of 8
char *controlledPointer;
};

Related

How to correctly align structs in C using posix_memalign?

I know that there have been many questions about this topic, but I still find myself confused.
I have written this simple program to help me visualize memory alignment in C:
#include <stdio.h>
#include <stdlib.h>
struct S{
int a;
short b;
char c;
};
int main()
{
struct S *s;
posix_memalign((void**)&s, 8, 12) == 0 ? printf("allocation successful"):printf("allocation failed");
printf("\nlocation of struct:\t%p\n", s);
printf("\nlocation of int:\t%p\nlocation of short:\t%p\nlocation of char:\t%p\n", &(s->a), &(s->b), &(s->c));
printf("\nsizeof struct: %lu\n", sizeof(s));
free(s);
return 0;
}
This is working well, but I am getting confused with the alignments.
Using these arguments (alignment=8 bytes, size=12):
allocation successful
location of struct: 0x205e010
location of int: 0x205e010
location of short: 0x205e014
location of char: 0x205e016
sizeof struct: 8
The int is the largest element of the struct, at 4 bytes. I can see here that the short begins 4 bytes later, and the char 2 bytes after that. Why isn't there another 2 bytes of padding between the short and char?
Also, why does the allocation fail if I use an alignment of 4 bytes? Since that is the size of the largest element in the struct, shouldn't it work?
allocation failed
location of struct: (nil)
location of int: (nil)
location of short: 0x4
location of char: 0x6
sizeof struct: 8
The char member can be aligned on any byte boundary; there is never a need to insert padding before a char member, even though a compiler could if it wanted to. The way it is laid out, there is just a single padding byte in the structure. If there was a gap after the short member, the structure would have five bytes of padding, which is wasteful.
The chances are that the minimum alignment that posix_memalign() supports is 8 on your machine. POSIX says it can fail:
[EINVAL]
The value of the alignment parameter is not a power of two multiple of sizeof(void *).
Having said that, it looks like sizeof(void *) is probably 4 (the addresses you print fit in a 32-bit address space). Maybe you should print errno (and/or strerror(errno)) to see what the cause of failure is.

behavior of sizeof operator?

#include<stdio.h>
struct krishna {
int i,j,k,l,m;
char c;
double d;
char g[48];
};
int main() {
struct krishna *me={0};
printf("%ld %ld\n",sizeof(me),sizeof(*me));//output is 8 80 how??
return 0;
}
Hello everyone I am new here and the compiler I use is gcc compiler in the above code can anyone explain why
1) pointer irrespective of any type is allocated 8 ?
2) sizeof the above struct is 80 ? Can anyone explain to me in general for any structure how can one determine the structure size , I am getting confused each time I expect one value but getting a different answer and I have also read other questions and answers in stack overflow regarding this and I am still not getting it.Please help.
printf("%ld %ld\n",sizeof(me),sizeof(*me));//output is 8 80 how??
Actually that should be:
printf("%zu %zu\n",sizeof(me),sizeof(*me));//output is 8 80 how??
"%zu" is the correct format string for a size_t value, such as the value you get from sizeof. "%ld" may happen to work on some systems (and apparently it does on yours), but you shouldn't count on that.
If your compiler doesn't support "%zu", you can use "%lu" (which expects an unsigned long argument) and explicitly convert the arguments:
printf("%lu %lu\n", (unsigned long)sizeof(me), (unsigned long)sizeof(*me));
You're getting 8 for sizeof(me) because that happens to be the size of a pointer on the compiler you're using (8 bytes, 64 bits). If you compiled and ran your program on a different system, you might get 4, because a lot of systems have 32-bit pointers. (And this assumes a byte is 8 bits, which is true for most systems but not guaranteed by the language.)
Most compilers make all pointers the same size, but that's not guaranteed by the language either. For example, on a word-addressed machine, an int* pointer could be just a machine-level address, but a char* pointer might need additional information to specify which byte within the word it points to. You're not very likely to run into a system with varying pointer sizes, but there's still no point in assuming that all pointers are the same size.
As for the size of the structure, that also can vary from one compiler to another. Here's your structure again:
struct krishna {
int i,j,k,l,m;
char c;
double d;
char g[48];
};
char is always exactly 1 byte, and char[48] is always exactly 48 bytes.
The number of bytes in an int can vary from one system to another; 4 bytes is most common these days.
The size of a double is typically 8 bytes, but this can also vary (though I don't think I've ever seen a system where sizeof (double) isn't 8 bytes.)
Structure members are laid out in the order in which they're declared, so your i will be at the very beginning of the structure, followed by j, k, and so forth.
Finally, the compiler will often insert padding bytes between members, or after the last member, so that each member is properly aligned. For example, on many systems a 4-byte int needs to be aligned at an offset that's a multiple of 4 bytes; if it's misaligned, access to it may be slow and/or very difficult.
The fact that sizeof (struct krishna) happens to be 80 bytes on your system isn't really all that important. It's more important to understand (a) the general rules compilers use to determine how structures are laid out, and (b) the fact that those rules can result in different layouts for different systems.
The language definition and your compiler guarantee that you can have objects of type struct krishna, and that you can access those objects and their members, getting back whatever values you stored in them. If you need to know how big a struct krishna is, the answer is simply sizeof (struct krishna). If, for some reason, you need to know more details than that (say, if you need to match some externally imposed layout), you can do some experiments and/or consult your compiler's documentation -- but be aware that the specifics will apply only to the compiler you're using on the system where you're using it. (Often an ABI for your system will constrain the compiler's choices.)
You can also use sizeof and offsetof (look it up) to find out where each member is allocated.
All pointers are addresses, and all addresses are the same size on a given system, usually 4 bytes on a 32 bit system and 8 bytes on a 64 bit system. Since you are getting 8, you must be on a 64 bit system.
The size of a struct depends on how the compiler "packs" the individual fields of the struct together into a single block of memory to contain the entire struct. In your case, your struct has 5 int fields (4 bytes each), a single char field (1 byte), a single double field (8 bytes), and a 48 character array. Add all that up and you get 20 + 1 + 8 + 48 = 77 bytes to store your data. The actual size is 80 because the compiler is "padding" the 1 byte char field with 3 extra unused bytes in order to keep all fields in the struct aligned to a 4-byte memory address, which is needed for good performance.
Hope that helps!
This is because:
sizeof( me ) // is a pointer.
... me is a pointer. The size of a pointer is a multiple of the word on your environment, hence it's common that on 32-bit environments a pointer is 4 bytes whereas on a 64-bit environment a pointer is 8 bytes (but not written in stone). If you were to go back a couple years, a 16-bit environment would have a 2 byte pointer. Looking at the next sizeof:
sizeof( *me ) // is a struct krishna, hence 80 bytes are needed to store it in memory.
... is a structure and the size of the structure krishna is 80 bytes. If you look at the structure:
struct krishna {
int i,j,k,l,m; // sizeof( int ) * 5
char c; // sizeof( char ) * 1
double d; // sizeof( double ) * 1
char g[48]; // sizeof( char ) * 48
// padding for memory address offset would be here.
};
... if you add up the amount of bytes required for each field and include the appropriate data structure alignment for the memory address offset then it will total 80 bytes (as expected). The reason it adds an extra 3 unused bytes is because to store a structure in memory it must be in a continuous block of memory that is allocated for the structure. For performance reasons, it will pad any size issues to ensure that the memory addresses are always a multiple of the word. The tradeoff of the 3 bytes for performance improvements is worth it, 3 bytes nowadays is not as impactful as the performance improvements the processor has when data alignment is guaranteed.
Just to add to answers of #Jacob Pollack and #ObjetDart, you can find more about structure padding at Structure padding in C.

How can I maintainably determine sizeof(struct ...)s?

Say I have a structure:
struct myStruct
{
int a;
short b;
char c;
};
In Windows, MSDN states that int takes 4 bytes, short takes 2 bytes and char takes 1 byte. This totals up to 7 bytes.
I understand that most compilers will pad structures with an unspecified number of bytes to improve alignment. So, when I execute this program,
#include <stdio.h>
int main(void) {
printf("%d\n", sizeof(struct myStruct));
return 0;
}
I get an output of 8. This means 1 byte was padded.
Is there any way I can maintainably determine struct sizes in code (short of adding up individual sizeofs)?
I ask this because later, if I need to change my structure to include about fifteen elements more and if I add five more structures, all my struct sizeofs will change causing things to get messy.
You can enforce it:
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
C_ASSERT(sizeof(struct myStruct) == 7); // or 8, whichever you want
Whenever the size diverges from 7, the code will simply cease to compile.
You can do similar things to enforce offsets of structure members. You'll need the offsetof() macro for that.
You can try pragma pack. It helps maintaining an alignment and has many flexibility. check this
http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp?topic=/com.ibm.xlcpp101.aix.doc/compiler_ref/pragma_pack.html
Update: just now saw your comment, perhaps pack is not your solution then

Force Specific Struct Size in C

For various reasons, I have some structs I want to force to be specific sizes (in this case 64 bytes and 512 bytes). Both however, are below the somewhat below the sizes I want them to be.
Is there anyway for me to tell the compiler to set them to these specific sizes and pad with zeros, or would I be best off just declaring an array inside the struct that makes up the excess space so that it aligns on the size I want?
You can use a union.
struct mystruct_s {
... /* who knows how long */
};
typedef union {
struct mystruct_s s;
unsigned char padding[512];
} mystruct;
This will ensure the union is 512 bytes or more. Then, you can ensure that it is no more than 512 bytes using a static assertion somewhere in your code:
/* Causes a compiler error if sizeof(mystruct) != 512 */
char array[sizeof(mystruct) != 512 ? -1 : 1];
If you are using C11, there is a better way to do this. I don't know anybody who uses C11 yet. The standard was published a matter of weeks ago.
_Static_assert(sizeof(mystruct) == 512, "mystruct must be 512 bytes");
Note that the only way to pad with zeroes is to put the zeroes there manually (calloc or memset). The compiler ignores padding bytes.
I don't think that there's any way to automatize this, at least in gcc which is the compiler I use. You have to pad your structs.
Be careful about automatic alignment of variables in your struct. For example
struct example{
char a;
int b;
}
does not take 5 bytes, but 8.

size of struct in C [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Why isn’t sizeof for a struct equal to the sum of sizeof of each member?
Consider the following C code:
#include <stdio.h>
struct employee
{
int id;
char name[30];
};
int main()
{
struct employee e1;
printf("%d %d %d", sizeof(e1.id), sizeof(e1.name), sizeof(e1));
return(0);
}
The output is:
4 30 36
Why is the size of the structure not equal to the sum of the sizes of its individual component variables?
The compiler may add padding for alignment requirements. Note that this applies not only to padding between the fields of a struct, but also may apply to the end of the struct (so that arrays of the structure type will have each element properly aligned).
For example:
struct foo_t {
int x;
char c;
};
Even though the c field doesn't need padding, the struct will generally have a sizeof(struct foo_t) == 8 (on a 32-bit system - rather a system with a 32-bit int type) because there will need to be 3 bytes of padding after the c field.
Note that the padding might not be required by the system (like x86 or Cortex M3) but compilers might still add it for performance reasons.
As mentioned, the C compiler will add padding for alignment requirements. These requirements often have to do with the memory subsystem. Some types of computers can only access memory lined up to some 'nice' value, like 4 bytes. This is often the same as the word length. Thus, the C compiler may align fields in your structure to this value to make them easier to access (e.g., 4 byte values should be 4 byte aligned) Further, it may pad the bottom of the structure to line up data which follows the structure. I believe there are other reasons as well. More info can be found at this wikipedia page.
Your default alignment is probably 4 bytes. Either the 30 byte element got 32, or the structure as a whole was rounded up to the next 4 byte interval.
Aligning to 6 bytes is not weird, because it is aligning to addresses multiple to 4.
So basically you have 34 bytes in your structure and the next structure should be placed on the address, that is multiple to 4. The closest value after 34 is 36. And this padding area counts into the size of the structure.

Resources