malloc and heap in c - c

consider the code below:
#include "list.h"
struct List
{
int size;
int* data;
};
List *list_create()
{
List *list;
printf("%d %d",sizeof(list),sizeof(List));
list = malloc(sizeof(list));
assert(list != NULL);
if (list != NULL) {
list->size = 0;
}
return list;
}
The number printed out is "4 8", i assume this is the 4 bytes taken by "int size" in List object?and the size of "int* data" is 0 cause nothing has assigned to data?
the size of int pointer is also 4 bytes so the type List take 8 bytes in total? or there are some thing else going on? Can some one help me understand all this in detail?
then the malloc() get 4 bytes from the heap and assign the address to the pointer list? later in main if i do "list->data[i]=1;" this will give me a run time error why? Is it because I cant change contents in the heap? but if i do "list->size++" this would work,
isn't the whole list object is in the heap?
really need some help here
Thanks in advance.

sizeof(List*) is the size of a pointer to a List struct.
sizeof(list) in your case, since variable list is of type List* is the same as sizeof(List*).
sizeof(List) instead is the size of the struct List, it contains two 32 bit variables (I assume you are using a 32 bit compiler obviously), an integer and a pointer and your compiler decided that the right size for your struct is 8 bytes.
Pointers to types are usually 4 byte in 32 bit compilers and 8 bytes in 64 bit compilers.
As a side note, reading your code however i read you never initialize list->data, you should initialize it to something somewhere i guess.
This is C++ however, you should write
typedef struct { ... } List; // This is C.
Sizeof operator is evaluated at compile time, not at runtime, it gives only information of the size of a type.
You cannot, for example, know how much elements are in a dynamic array with sizeof, if you were trying to accomplish this, sizeof(pointer) will give you the size in byte of the pointer type.
As something to read about what is a pointer and what is an array i would suggest you to read http://www.lysator.liu.se/c/c-faq/c-2.html or http://pw1.netcom.com/~tjensen/ptr/pointers.htm

Technically your code has an error in it.
The code should read: sizeof(struct List) or have typedef struct List List; somewhere.
But yes, sizeof(list) is the size of the variable list. Since list is a pointer it is equivalent to sizeof(void*) which on your system/compiler is 4.
sizeof(struct List) is the size of the struct which is sizeof(int)+sizeof(int*)+any alignment issues. The alignment thing is often forgotten but is very important as it can change the size of the struct in unexpected ways.

Related

the difference between struct with flexible arrays members and struct with pointer members

I'm quit confused with the difference between flexible arrays and pointer as struct members. Someone suggested, struct with pointers need malloc twice. However, consider the following code:
struct Vector {
size_t size;
double *data;
};
int len = 20;
struct Vector* newVector = malloc(sizeof *newVector + len * sizeof*newVector->data);
printf("%p\n",newVector->data);//print 0x0
newVector->data =(double*)((char*)newVector + sizeof*newVector);
// do sth
free(newVector);
I find a difference is that the address of data member of Vector is not defined. The programmer need to convert to "find" the exactly address. However, if defined Vector as:
struct Vector {
size_t size;
double data[];
};
Then the address of data is defined.
I am wondering whether it is safe and able to malloc struct with pointers like this, and what is the exactly reason programmers malloc twice when using struct with pointers.
The difference is how the struct is stored. In the first example you over-allocate memory but that doesn't magically mean that the data pointer gets set to point at that memory. Its value after malloc is in fact indeterminate, so you can't reliably print it.
Sure, you can set that pointer to point beyond the part allocated by the struct itself, but that means potentially slower access since you need to go through the pointer each time. Also you allocate the pointer itself as extra space (and potentially extra padding because of it), whereas in a flexible array member sizeof doesn't count the flexible array member. Your first design is overall much more cumbersome than the flexible version, but other than that well-defined.
The reason why people malloc twice when using a struct with pointers could either be that they aren't aware of flexible array members or using C90, or alternatively that the code isn't performance-critical and they just don't care about the overhead caused by fragmented allocation.
I am wondering whether it is safe and able to malloc struct with pointers like this, and what is the exactly reason programmers malloc twice when using struct with pointers.
If you use pointer method and malloc only once, there is one extra thing you need to care of in the calculation: alignment.
Let's add one extra field to the structure:
struct Vector {
size_t size;
uint32_t extra;
double *data;
};
Let's assume that we are on system where each field is 4 bytes, there is no trailing padding on struct and total size is 12 bytes. Let's also assume that double is 8 bytes and requires alignment to 8 bytes.
Now there is a problem: expression (char*)newVector + sizeof*newVector no longer gives address that is divisible by 8. There needs to be manual padding of 4 bytes between structure and data. This complicates the malloc size calculation and data pointer offset calculation.
So the main reason you see 1 malloc pointer version less, is that it is harder to get right. With pointer and 2 mallocs, or flexible array member, compiler takes care of necessary alignment calculation and padding so you don't have to.

How can i identify the size of structure member?

struct busData{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
int main(){
struct busData *bus = (struct busData*)calloc(5, sizeof(struct busData));
printf("\n%d", sizeof(bus)); //result is 4
free(bus);
return 0;
}
Now It is showing '4' or '8'depending on platform as a result. I think it should display 5040 right? Because I gave 5 value with calloc(). So how can I get 5040? i am using the 3 elements until 'bus+2' and then I am freeing up with free(bus); And i want to know how many elements left (it should show 2008). so i need 5040?
sizeof(bus)
Here bus is a pointer so sizeof() will return 4 which is the size of the pointer in the platform you used.(depending on the platform used).
If you want to know the size of struct use sizeof(struct busData) or sizeof(*bus)
You are trying to output the size of the pointer bus instead of the 5 objects pointed to by the pointer.
Try the following demonstrative program
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1000
struct busData
{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
int main(void)
{
struct busData *bus = (struct busData*)calloc(5, sizeof(struct busData));
printf("\n%zu\n", 5 * sizeof( *bus ) );
return 0;
}
The program output is
5040
Pay attention to the conversion specifier and the expression used as an argument of the printf call
printf("\n%zu\n", 5 * sizeof( *bus ) );
^^ ^^^^^^^^^^^^^^^^^
Take into account that pointers do not provide information whether they point to a single object or first object of an array of objects. So using the pointer bus you have to specify explicitly how many objects are pointed to by the pointer.
The same result you could get executing the following statement
printf("\n%zu\n", sizeof( struct busData[5] ) );
Now It is showing '4' as a result. I think it should display 5040 right?
No, you're wrong. Check the data types.
First of all, a little about sizeof operator, from C11, chapter ยง6.5.3.4
The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of
the operand. [...]
bus is a pointer, so, sizeof(bus) is the same as sizeof (struct busData*), which is the size of a pointer, which depending on your environment, can give you the result, of which, the common nones are 4 or 8.
After that, there can be padding in between structure elements and at the end, so a structure defined like
struct busData{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
defining a variable of that type and trying to check the size via sizeof may not give you (4+1000+1) == 1005 bytes, for most of the environments.
Quoting again,
[....] When
applied to an operand that has structure or union type, the result is the total number of
bytes in such an object, including internal and trailing padding.
So, you need to account for padding also.
That said,
printf("\n%d", sizeof(bus));
actually causes undefined behavior. You need to write
printf("\n%zu", sizeof(bus));
as sizeof yields a result of type size_t.
I think the code is screwed up from the beginning.
The problem with sizeof was already explained in other answers.
Another big problem is this:
Because I gave 5 value with calloc(). So how can I get 5040?
i am using the 3 elements until 'bus+2'
and then I am freeing up with free(bus);
And i want to know how many elements left (it should show 2008).
so i need 5040?
This sounds like you want to use the remaining 2 elemens after calling free.
First:
you have 1 pointer. The compiler can tell you the size of the pointer and the size of the single element that the pointer is pointing to.
The compiler has no idea that you allocated memory for more than 1 element of that type and hence cannot tell you anything different than size of pointer or size of 1 element.
Second:
There is no concept like "using" some memory. For the compiler and the OS it doesn't matter if you write something to the memory location or not. It doesn't care if some bytes are still (or again) filled with 0.
Third:
If you allocate a block of memory and free it again, the whole block is free'd and mustn't be used any longer. If you expect to have 2008 bytes that you still can use, you are wrong! Your pointer will point to an invalid address after free is called. Using that pointer to access the memory afterwards is undefined behaviour
How can i identify the size of structure member?
With a pointer to dynamic allocated memory, there is no way to know the size of memory that the pointer points to.
If you need to know the size after the malloc/calloc, you'll simply have to "remember" how much you malloc/calloced, i.e. save it in a variable.
You could wrap it inside another struct and provide a create function. Something like:
struct busData{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
struct busDataContainer{
size_t size;
struct busData* busData;
};
struct busDataContainer createBusData(size_t n)
{
struct busDataContainer c;
c.size = n * sizeof(struct busData);
c.busData = calloc(n, sizeof(struct busData));
return c;
}
int main(){
struct busDataContainer bus = createBusData(5);
printf("\n%zu", bus.size;
return 0;
}

How much memory allocated for node in C?

typedef struct Node {
int data;
struct Node *next;
} node;
pointer->next = (node*)malloc(sizeof(node));
How many bytes of memory are dynamically given to pointer->next in the above code. For (int*)malloc(sizeof(int)), 2 bytes are given. Likewise how many for node?
Malloc will dinamically assign the size of "node".
Node is a struct and the size of every struct depends on the size of every element inside the struct.
In this case, the size of node will be: size of int + size of struct Node*
(If the result is not multiple of 2, it will be padded for architecture reasons)
Your device has an architecture of 2 bytes, and for that reason, the size of the structs can only be 2, 4, 6, 8 etc...
The size of int depends on the target you are working on. Since your architecture is 16 bits, the size of int is 2 bytes.
About. the size of struct Node *, you need to know that EVERY pointer data types have exactly the same size, it doesn't matter the data type their are pointing to. And that size also depends on the architecture. Again, your architecture is 16 bits and that's why the size of struct node * is 2 bytes.
size of int = 2.
size of struct node * = 2
Total memory assigned by malloc = 2 + 2 = 4
First, a suggestion: rewrite
pointer->next=(node*)malloc(sizeof(node));
as
pointer->next = malloc( sizeof *pointer->next );
You don't need the cast (unless you're working on a pre-ANSI implementation, in which case God help you), and using the dereferenced target as the operand of sizeof means you don't have to specify the type, potentially saving you some maintenance heartburn.
Also, a little whitespace goes a long way (although you don't need to put whitespace around the function arguments - that's my style, some people don't like it, but it makes things easier for me to read).
How much bytes of memory is dynamically given to pointer->next
It will be at least as big as sizeof (int) plus sizeof (struct Node *), and potentially may be bigger; depending on your platform, it could be as small as 4 bytes or as large as 16. C allows for "padding" bytes between struct members to satisfy alignment requirements for the underlying architecture. For example, a particular architecture may require that all multi-byte objects be aligned on addresses that are multiples of 4; if your data member is only 2 bytes wide, then there will be 2 unused bytes between it and the next member.
Without knowing a lot about your system, we just can't tell you. You can take that same code and try it on multiple compilers, and you'll get different answers. You have to check yourself, using sizeof(node) or sizeof(struct Node) (I think either syntax works, but just in case).

Array of pointers confusion with skip list

I think I have a basic understanding of how skip lists work, but being new to them in addition to being a C-beginner has me confused on a few points, especially the initialization of the list. Here's the code I'm trying to follow:
#define MAXSKIPLEVEL 5
typedef struct Node {
int data;
struct Node *next[1];
} Node;
typedef struct SkipList {
Node *header;
int level;
} SkipList;
// Initialize skip list
SkipList* initList() {
SkipList *list = calloc(1, sizeof(SkipList));
if ((list->header = calloc(1, sizeof(Node) + MAXSKIPLEVEL*sizeof(Node*))) == 0) {
printf("Memory Error\n");
exit(1);
}
for (int i = 0; i < MAXSKIPLEVEL; i++)
list->header->next[i] = list->header;
return list;
}
I haven't done anything with arrays of pointers yet in C, so I think I'm getting a bit caught up with how they work. I have a few questions if someone would be kind enough to help me out.
First, I did sizeof(int) and got 4, sizeof(Node*) and got 8, so I expected sizeof(Node) to equal 12, but it ended up being 16, why is this? Same confusion with the size of SkipList compared to the sizes of its contents. I took the typedef and [1] out to see if either of them was the cause, but the size was still 16.
Second, why is the [1] in struct Node *next[1]? Is it needed for the list->header->next[i] later on? Is it okay that next[i] will go higher than 1? Is it just because the number of pointers for each node is variable, so you make it an array then increase it individually later on?
Third, why does list->header->next[i] = list->header initially instead of NULL?
Any advice/comments are greatly appreciated, thanks.
For your first question - why isn't the size of the struct the size of its members? - this is due to struct padding, where the compiler, usually for alignment reasons, may add in extra blank space between or after members of a struct in order to get the size up to a nice multiple of some fundamental size (often 8 or 16). There's no portable way to force the size of the struct to be exactly the size of its members, though most compilers have some custom switches you can flip to do this.
For your second question - why the [1]? - the idea here is that when you actually allocate one of the node structs, you'll overallocate the space so that the memory at the end of the struct can be used for the pointers. By creating an array of length one and then overallocating the space, you make it syntactically convenient to access this overallocated space as though it were a part of the struct all along. Newer versions of C have a concept called flexible array members that have supplanted this technique; I'd recommend Googling it and seeing if that helps out.
For your final question - why does list->header->next[i] initially point to list->header rather than NULL? - without seeing more of the code it's hard to say. Many implementations of linked list structures use some sort of trick like this to avoid having to special-case on NULL in the implementation, and it's entirely possible that this sort of trick is getting used here as well.
The sizeof number is 16 because of structure padding.
Many architectures either require or strongly prefer their pointers to be aligned on a certain boundary (e.g., 4-byte boundary, 8-byte boundary, etc.) They will either fail, or they will perform slowly, if pointers are "misaligned". Your C compiler is probably inserting 4 unused bytes in the middle of your structure so that your 8-byte pointer is aligned on an 8-byte boundary, which causes the structure size to increase by 4 bytes.
There is more explanation available from the C FAQ.

malloc pointer identification

So I have this assignment to implement my own malloc and free in C. The problem is one of the requirements for the memory_free(void *ptr) function. It has to return 1 if the pointer is invalid, i.e. it hasn't been allocated by the memory_alloc(unsigned int size), or return 0 otherwise. I just can't figure out a way to do this, without it being absolutely time inefficient.
So my memory structure is this: I have a global pointer to the beginning of the array I get to act as a heap. Every block of memory has an int header to tell the size of it and whether it's free or not.
This is my memory_free(void *ptr) function right now, TYPE is typedef unsigned int:
int memory_free(void *ptr)
{
void *head = ptr;
if (head == NULL)
return 1;
head -= sizeof(TYPE);
if (!((*(TYPE*) head) & 1 ))
return 1;
(*(TYPE*) head) &= ~0x1;
return 0;
}
The pointer ptr points to the first byte of user block, which means that if I want to read the header, I have to go back 4 bytes. One solution to check the validity of the pointer is to go through the heap from the beginning and see if I get on the header in question, but that's not time efficient. Could anyone tell me a better way?
One O(1) solution would be to make the header 8 bytes instead of four; use the extra four bytes to indicate validity. For example, it could be the one's complement of what you store in the other four bytes. So you look at the header and if those extra bytes contain anything other than the one's complement of the first part of the header, you know it's not a valid block.
I see 2 possible alternatives:
Keep a linked list of pointers that you have allocated : filled by memory_alloc and consumed by memory_free. This way you can double-check if what has been passed to memory_free is coherent.
The linked-list might be time-consuming: as a compromise you can just store the addresses of the beginning and the end of your memory pool and just ensure that pointers passed to memory_free are in the correct bound. Its far less precise and sure but faster.

Resources