Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Is malloc used to specify at compile time - a maximum size of a buffer(array) pointed to by a pointer and then allocated that max sized buffer by default in run-time and later - only that part of the buffer is actually used (though full size was allocated) that we need (by taking data from user etc) ?
If the above is true - then that means malloc (used along pointers) essentially provides a way to model a (including higher dimensions - but for eg -2) 2-D array as a 1-d array of pointers, and then at compile time specify the size of buffer to be allocated to each individual pointer i.e. essentially accomplishing the same thing as declaring it as a 2-D array with max dimensions specified in declaration at compile time - but just allowing to model/visualize it differently. Both are allocated the default max size - array type declaration at the the run of the declaration statement, while pointer+ malloc type at the run of the malloc statement (I do think this size information is used in both cases to calculate the size of stack+heap sum required for run).
That is in pointer+malloc, once compiler sees that this information (max buffer size for each pointer using malloc) is available at compile time - compilation can go through as it has the information of how much memory to allocate by default and can (and does) also use that information to calculate the size of stack+heap sum required for the function run (if no malloc - then it points to a single element). Later at run-time - the max sized buffer is allocated after malloc statement is run, to be later used as input needs.
There is a reason why allocating memory using malloc, calloc and realloc is called dynamic memory management. Dynamic in this context means that which happens at run-time. This does not happen at compile time.
If the above is true...
Since it is not true, what follows is not derivable from it.
malloc is a function of the standard C library.
All functions are called at runtime.
The only thing that happens at compile time is creating a function call to malloc
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am given a C project assignment in which I am asked to implement a simple memory management library. The way it works is that it has init function which takes a pointer(void*) to a chunk of memory allocated by another c program along with the size of the chunk and has two other functions to allocate a block of requested size from the said chunk and deallocate a block when passed back the pointer pointing to it.
Problem is that I am asked to keep my management structures inside the chunk itself and I have zero idea on how to do that. I thought about dividing the chunk into frames but how can I keep track of which frames are allocated without using anything from outside the chunk?
Edit: Init function is used like this. There is this program which will call the library I am going to write. It will allocate a chunk of memory using either malloc or calloc. Then it will call the init function from the library and pass the pointer to that memory chunk along with the size of the chunk to it.
What my library will do with that chunk is to allocate blocks from it on demand. So my library's allocate function actually is a call to request a block of memory(size is passed as an argument) from the chunk. And it will return a (void *) pointer pointing to the allocated memory block.
Edit2: To make the situation more clear, my library has to be able to allocate and deallocate which means holes will appear in the chunk it is managing and it will employ either first-fit, best-fit or worst-fit.
Edit3: Is there a way to convert memory addresses into long int?
Here's a rough idea of what you would need to do:
The memory segment should be structured as a linked list of blocks. Each block starts with a copy of your management structure followed by the memory that you allocate.
On initialization, point the head of the linked list to the start of the given memory segment. Set the size to the size of the segment minus the size of the management structure, and set the next pointer to NULL.
When the first allocation request is made, set the size of the head block to the requested size, then set the next pointer to the memory immediately after that. Set the size of the new block to the old head size minus the requested size and the size of the management struct.
For a deallocation, you would need to find the block prior to the one you're about to release. Change the size of the prior block to the size of the freed block plus the struct size, then change the next pointer to the freed block's next pointer.
That should be enough to get you started.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
In C, we can allocate memory automatically or dynamically:
size_t foo = 128;
char str1[64]; // Automatic
char str2[foo] // Automatic (variable-length, C99)
char *str3 = malloc(64); // Dynamic
char *str4 = malloc(foo); // Dynamic
With automatic allocation, variables have a limited scope and the memory is usually allocated on the stack, whereas dynamic allocation uses the heap.
Let's stick with strings and say a function is supposed to return a string that it somehow creates. There seem to be two common practices, both can be seen with standard library functions:
Take a buffer and a size, then write into the provided buffer
Allocate a buffer with malloc() and return the pointer to it
The first has the advantage that we don't need to remember to free() the memory. On the other hand, we need to hand in two additional arguments and somehow need to determine from the outside what size the buffer should have:
char str1[128]; // Let's hope this is large enough!
fill_my_buffer(str1, 128); // Might need more than 128, who knows
char *str2 = return_a_ptr(); // Just give me a pointer
size_t len = strlen(str2); // Ah, so that's what we got!
What (other) considerations should be taken into account when choosing between automatic or dynamic memory allocation in C?
The question was closed as opinion-based, but I'm convinced it should be possible to compile a comprehensive list of objective pros and cons for either approach, which would then allow making informed decision on a case-by-case basis.
One rule of thumb is that you should avoid "large" allocations on the stack. A page (4096 bytes) or two is fine, but anything larger should be heap-allocated.
Changing the stack pointer too much will kill your cache performance, and cache is king.
Also, you might overflow the stack and miss the guard page, although this is mostly only a problem with threads which necessarily have limited-size stacks, or else on otherwise constrained systems which can't have automatic main-thread stack growth.
Other than that, the main question is semantics: does this (small) object "belong" to this stack frame, or does it need to live for a different period of time (longer or shorter).
The need to call free should not be a concern at all, there are all sorts of functions that always must be called in pairs (which is the main problem that C++ tried to address, and also GNU's __attribute__((cleanup)) extension) and you should develop the discipline of always knowing to do it.
Notably, every function that takes a pointer should have a concept of "who is in charge of this ownership"? Common ownership models include: borrowed (owned by some higher stack frame), uniquely-owned, and shared (often refcounted) ownership, although there can be dozens of subtle variants (though not all in the same program).
It's basically a judgement call ā can the calling code know how big a buffer is likely to be?
If so, it is probably better that it provides the buffer and the called code must ensure it doesn't overflow it (which in turn means that the interface must specify the size of the buffer provided).
If not, then the called code should allocate and return the memory.
The complication with the caller-provided buffer is "what to do when the provided space isn't big enough". The complications with the caller-provided buffer are ensuring it is freed appropriately and deciding what to do if memory allocation fails.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Iām stuck trying to figure out what, exactly, are the definitions of the following stack implementations and the advantages and disadvantages associated with each.
1.Array-based implementation
2.Linked implementation
3.Blocked implementation
Any help would be much appreciated.
A user of a stack implementation expects a dynamic data structure. C does not provide that directly in language terms. You have to allocate and administrate the memory your own.
Allocating an array, therefore a static sized structure, is very easy. However, you have the problem, that the number of maximum entries is limited. If you make the array too small, this will cause errors, if you make the array very big, you are waisting memory.
A solution for this is to dynamically reallocate the array, if the number of entries exceeds the array size. But this moves the whole memory to another place in memory, what has some disadvantages. (I. e. you have to copy the whole memroy and it is not possible to hold a pointer to a specific entry.)
Having a linked list is the contrary. You (dynamically) allocate memory for each entry. You can free the memory for a single entry on removing from stack. This sounds better, but has the caveat, that you spent a pointer size of memory for each entry. Typically this is the size for an entry. So you double the memory consumption. Beside this, allocating small pieces of memory over and over wastes memory, too.
So you can implement a compromise: A linked list of arrays: You allocate a block for a number of entries, let's say 256. Then you fill that block with entries, without reallocating or allocating memory. If the number of entries exceeds that value, you allocate a new block for additional 256 entries. The blocks are linked. So it is a linked list of arrays.
Esp. for a stack ā you do not have removals in the middle of the structure ā this is the best implementation in most cases.
Think about how much space each data structure takes, and whether you can do the stack operations on them efficiently; i.e., in O(1) time.
For a basic stack, you need to be able to push new elements onto the stack, and pop the most recently pushed (top) element off. You probably also want to peek at the top element, and check if the stack is empty.
A dynamically sized array (or block, if I understand the OP's comment correctly) is fine for a stack. It may be advantageous in certain situations if you will be accessing and changing the stack a lot, and want to avoid the small amount of extra work of allocating and destroying memory with each push or pop. It also gives you direct, indexed access to everything in the stack, for extended functionality. The disadvantage is that the stack will use some extra space.
You can use a singly-linked-list list for a stack as well, pushing and popping at the head. This is probably the most common type structure used if you don't need extended functionality like direct access to the elements besides the head, and if you aren't trying to implement something on the bleeding edge of time efficiency.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
free() only needs the pointer value to release allocated memory. Which means that C knows how big assigned memory blocks are. Then how come there isn't some built-in function to find the size of a pointer array?
I know the convention is to keep track of array sizes, but given that there already is some memory management happening natively, why don't we harness that to have a convenient size() function for arrays?
Such a function would be possible. The question is why the C standard doesn't require it.
The GNU C library implementation provides a function malloc_usable_size() that's similar to what you're suggesting. It returns the number of usable bytes for a malloc()ed pointer -- which may be greater than the requested size for various reasons.
It's not 100% clear why no such function is in the standard. It's not mentioned in the 1989 ANSI C Rationale or in the ISO C99 Rationale.
One thing to keep in mind is that an implementation doesn't need to keep track of the number of bytes requested by a malloc() call. It will often round up the request to some larger value, and it only needs to keep track of that.
For that matter, free() doesn't necessarily need to know the size of the block being deallocated. It might just call some lower-level function that doesn't provide that information. Or, for example, allocated blocks might b organized into linked lists, one list for each allocated size; free() might simply release a block from that list without having to know the size.
Finally, C programmers have gotten along without such a function for decades. Adding a requirement to provide it would impose some (probably fairly small) overhead on all implementations. I think the attitude is that you can simply remember how much memory you asked for, and use that information as needed.
If you allocate a single object:
some_type *ptr = malloc(sizeof *ptr);
then sizeof *ptr gives you the size of the object. If you allocate an array:
some_type *ptr = malloc(count * sizeof *ptr);
then sizeof *ptr only gives you the size of a single element of the allocated array -- but if you remember the value of count you can compute the total requested size easily enough.
Bottom line: The C standard could have required such a function, but it's not really necessary.
UPDATE: Kerrek SB makes an excellent point in a comment, one that I hadn't thought of. I'll take the liberty of summarizing it here.
A function that operates on an array via a pointer to its initial element (and there are a lot of such functions) shouldn't have to care how the array was allocated. The proposed size() function, like the GNU-specific malloc_usable_size(), works only when the argument points to a heap-allocated array. This means that the function either has to assume that the array is heap-allocated (and be right about that assumption!) or be given extra information. In the latter case, it might as well be given the size of the array, making size() superfluous.
free() may use internal data to reclaim the block of memory being released, but be aware that this data does not necessarily contain the exact size passed to malloc(), calloc(), or realloc() to allocate the block. The C Standard does not specify a function to retrieve this information.
Most malloc() implementations provide a non-standard function to retrieve the available size of the allocated block: in the Glibc, this function is size_t malloc_usable_size(void *ptr);. Other libraries may have a different function or no function at all to retrieve this information.
As for a generic solution to retrieve the size of the array to which you have a pointer, this is usually not possible. In efficient implementations, pointers do not carry size information. It is possible to implement fat pointers that would carry this information, but the whole system needs to be compiled this way. Some integrated compilers such as tcc support this approach to provide runtime pointer checking.
Because basically, the address will point on a chunk of memory, which contains meta-data (such as the size of the chunk). Freeing that entry will actually mark the block available (if the pointer is valid).
If the caller access that memory location afterward, that's undefined behaviour. So even from that point of view, free will have its job done.
free() only needs the pointer value,because you can only pass the pointer that malloc() return.The malloc() will write the size of this assign in the front address of return pointer.When you pass the pointer to free(),free() will read the size,so free() knows how many space to release.Therefor,there not used any function to find the size of a pointer array.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C programming : How does free know how much to free?
A random thought occured to me that how comes free(myPtr) doesn't need a length parameter? How does it know how much memory to free?
I can only guess that it keeps track of how much memory it allocates for each particular start address.
This is because malloc saves the information about the length of the allocated chunk, usually in a spot that precedes the address returned to your program. It is not unusual for implementations to allocate an extra storage for a size_t, put the size there, add sizeof(size_t), and return it to you as the malloc-ed pointer. The standard does not call for this implementation, thoug, so alternative implementations are possible, e.g. based on a hash table.
When C allocates memory, it records the length associated with the pointer it gives you. (Often in the area just before the block of memory. But that's an implementation detail.) It keeps some kind of table or list of memory blocks it's handed out, and when you free that memory, C looks up the length of that block based on the value of the pointer.
That's part of why the pointer you pass to free has to be exactly equal to the one you get back from malloc. If it's not, C gets confused and can't find the correct memory block (or its length), and may very well end up "freeing" some memory it was never meant to touch. (If it does that, you may end up with a condition called "heap corruption", which is really bad -- from then on, C might do all kinds of wacky stuff, like trying to allocate some memory in the middle of an existing block and mangling whatever's there.)