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 8 years ago.
Improve this question
I wanted to test malloc() to see if allocating to the same adress twice adds up to the memory, or just replaces it: int *ptr = malloc(sizeof(int)); ptr = malloc(2*sizeof(int)); Will this memory be 3 ints large or just 2 ?
When I test how many ints can fit in, I get about 200, after which I get errors during runtime. Can someone please explain the randomness of memory allocation ?
malloc() always allocates a new block of memory, of the size you request, assuming that memory is available. It returns a pointer to the first byte of the memory it allocated so that you can use it. When you do your second malloc() call, it overwrites the pointer to the memory you allocated in the first, so you can't access it anymore - but it's still there and it's still allocated to you. This is usually called a memory leak, because your process has grabbed memory and then not given it back despite no longer using it.
So after your second call, you've allocated enough memory to store three integers, in two separate blocks, the first of which can no longer be accessed because you don't have a pointer to it anymore.
There is no randomness in memory allocation.
I'm not sure why you're getting runtime errors when you get to 200 ints, unless your process has very constrained memory availability. It'd help to know what the errors you're getting actually are.
Will this memory be 3 ints large or just 2 ?
ptr will point to memory for two ints when you reassign to ptr the previous memory location is now lost and that memory is leaked.
malloc simply return void pointer to the allocated memory.2*sizeof(int) will allocate 2*sizeof(int) bytes means memory for two integers.
Initially you gave memory for one integer only then again on same pointer you assigned memory for two integer.So finally it will point for two integer size space.
Related
I'm trying to figure out how many bytes in a block are taken up by the boundary tags. I have been told that when trying to malloc an adjacent block of memory, a "jump" will appear in assembly code, and I can use that to determine the size of the boundary tag. I've tried this:
int* arr = malloc(8);
arr++;
arr = malloc(8);
But there isn't any jump in assembly code. Am I "trying to malloc an adjacent block of memory"?
EDIT: I think he means a jump will appear between address value. I use the beginning of the second block of memory subtract the payload size of the first block. But I'm still confused, how could I malloc an adjacent block of memory?
Unless you're writing an actual memory allocator, you can't actually allocate two consecutive chunks of memory. If you want to see some pretty gnarly code which does this, have a look at the Illumos malloc https://github.com/illumos/illumos-gate/blob/master/usr/src/lib/libc/port/gen/malloc.c.
If you want to see how Illumos (and Solaris) handle the redzone between allocated blocks, you should trawl through https://github.com/illumos/illumos-gate/tree/master/usr/src/lib/libumem/common.
The memory consumed by malloc(3) requires, for proper management of the actually used memory, of some structures that must be dynamically allocated also. For this reason, many allocators just do allocate the space required for the management data adjacent to the block space dedicated to the user. This makes that normally two consecutive junks of memory allocated by malloc(2) show some gap in their addresses.
There are other reasons to see gaps, one fundamental is that malloc normally gives you aligned memory addresses, so it is warranted that the data you store on that memory will be properly aligned.
And of course, there can be implementations (normally when heap allocation should be more robust in respect to buffer overruns) that the memory dedicated to storage of management data is completely unrelated and apart off the final given memory. In this case you could observe no gaps between memory allocations on some cases.
Anyway, your code has serious bugs, let's see:
int* arr = malloc(8);
You had better here to acquire just the memory you need, using the sizeof operator, as in int *arr = malloc(sizeof *arr); instead.
arr++;
this statement is useless, as you are going to overwrite the value of arr (the pointer) with new assignment statement after it from malloc(), so it is of no use to increment the pointer value. You also are somewhat losing the returned value of the previous malloc() (which is essential in order to return the allocated memory, but read below).
arr = malloc(8);
Until here, you had the chance to --arr decrementing the value of arr in order to be capable of free(3) that block. But this statement overwrites the value stored in arr so the previous pointer value is overwritten by the new pointer. Memory you acquired on the first malloc has no way to be accessed again. This is what is commonly known as a memory leak, and is normally a serious error (very difficult to catch) on long run programs (like servers or system daemons). The program allocates a bunch of memory in the inner part of a loop, that is not returned back with a call to free(3), so the program begins growing and growing until it exhausts all the available memory.
A final note, I don't understand what did you mean with malloc adjacent block of memory. Did you believe that incrementing the pointer would make malloc() to give you a special block of memory?
First, malloc has no idea of what are you going to do with the pointer it gives to you.
But also, it doesn't know anything about the variable contents of the pointer you are assigning to (you can even not store it in a variable, and pass it as another parameter to another functions) So there's no possibility for malloc to know that you have incremented the pointer value, or even the pointer location, from its body.
I cannot guess your interpretation. It would be nice to know what has made you to think that you can control how malloc(3) selects the block of memory to give to you. You have no control on the internals of malloc() You just specify the amount of continous memory you want, and mallocs provides it, giving you a pointer pointing to the start of that block. You cannot assume that the next time you call malloc (with the same or different amount of memory) it will give you an adjacent block. It just can be completely unrelated (above or below in memory) to the previous given block. And you cannot modify that pointer, because you need it to call free(3) once you don't need the block anymore, with exactly the same pointer value that malloc(3) gave to you. If, for some reason you modify the pointer, you need to restore it to the original value to be capable of calling free(3). Lack to do so, you'll probably crash your program at the next call to free(3).
I just see a memory leak. Malloc 2 times into different vars 8 bytes of space and see if the difference is more than 8 bytes or 2 int.
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 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 5 years ago.
Improve this question
Seems comments/answers just simply stops at C standard description, let's discuss a bit more deep with implementation specific.
I saw below code in other discussion:
struct { size_t x; char a[]; } *p;
p = malloc(sizeof *p + 100);
if (p)
{
/* You can now access up to p->a[99] safely */
}
Then what if keep accessing p->a[i], 99< i < 0xffff or even bigger value?
malloc implementation should have a virtual memory block backed area for "(sizeof *p + 100)", so after "i" exceeds 100, initially it should be just corrupt data within the virtual memory block which might be non harmful.
if later "i" exceed that virtual memory block size, while next block is available and is never physical memory backed up(means ready to be allocated), would copy-on-write in kernel physical memory happens for next block on this bad access? And would malloc() later aware of this?
if next block is not in heap management, should p->a[i] get a virtual memory access violation error? Because malloc() is not called, so brk/sbrk won't be triggered to expand memory region of process heap.
Just curious how damage it is in this case...
Accessing stuff outside of the allocated memory is undefined behavior. Anything can happen. I hear nasal demons are a possibility.
If you are really lucky, you might get an access violation/segfault. If you aren't lucky, then some other variable in the program may be overwritten, or nothing observable may happen, The moon may turn into the 7UP logo, or maybe something nasty squeezes out of your right nostril.
This question already has an answer here:
free char*: invalid next size (fast) [duplicate]
(1 answer)
Closed 8 years ago.
Code snippet, at the bottom, which I was trying lead to the following error
free(): invalid next size (fast)
Above error, was caused by declaration of integer variable mock after accidently calling memset() on pointer check with size more than what was originally allocated using malloc(). And when free() is called on pointer check it leads to a runtime error.
It would be helpful if somebody could explain how the internal memory is being manipulated or why this error actually occurred.
Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *check = (char *)malloc(sizeof(char) * 10);
memset(check, 0, 100);
memcpy(check, "memsetcpy", 10);
int mock = 9;
free(check);
return 1;
}
EDIT My intention of asking the question was to know/understand what happens to the book-keeping information in the heap memory when the program runs. And may be to have some information on data structures that are modified would be great.
OR I wanted to know from the design perspective.
Thanks everyone for chipping-in.
When the program writes outside defined memory space, anything could happen.
In this case, the program has damaged the heap.
This is the signature of memset:
void * memset ( void * ptr, int value, size_t num );
With malloc, you allocate 10 bytes of memory, and assign a pointer to that memory to check. (Not a solution, but you should not cast the return value of malloc)
Then with memset, you write 100 bytes of zeroes to the block of memory pointed to by check.
Your program writes correctly to the first ten bytes, then zeroes out whatever is in the 90 following the allocated space. Since you're writing outside of allocated memory, anything could happen, and in this case, I'd guess you're writing over memory that contains bookkeeping info for the malloc/free memory allocation system. Of course, since you're invoking undefined behavior, it would also be acceptable for it to cause your computer to grow legs and walk away.
A typical dynamic memory (heap) implementation stores a lot of household information right there, in the very same memory, interleaved with user data. Each block of memory you allocate typically includes a special header region and, possibly, a special footer region. These regions surround your user region from both ends. You are only allowed to manipulate memory inside your user region. But the moment you write anything outside the boundaries of that user region, you most certainly damage those internal header and footer regions. This completely destroys the integrity of dynamic memory management subsystem. The rest follows.
In your case you go outside your user region by 90 bytes. This is a lot. You probably destroyed a lot of internal household data that is critical for proper operation of dynamic memory.
The specific details of this (what gets damaged and how it affects free later) are very, very, very implementation-dependent. Different implementations can be wildly different in that regard. There's no way to provide a more specific description without at least knowing what specific implementation you are using.
In modern operating systems, allocated memory is managed in very large chunks from kernel space and then allocated in smaller chunks by user space code.
The user space code keeps track of the allocated and free memory typically through the use of a doubly linked list along with sentinel data before and after each allocated chunk. The sentinel data includes things like a magic number, chunk size, etc.
The sentinel data helps the memory manager detect when a user program writes past (or before) it's allocated size. The use of a doubly linked list helps the memory manager combine the freed smaller chunks into larger freed segments to help avoid fragmentation.
When you write beyond your allocated size, you not only destroy the sentinel data but also probably the linked-list data. Once the linked list gets destroyed, most memory managers fall apart thus the comments about things going off the reservation.
Hope this helps.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to avoid memory allocations to construct the path for device
char *device;
const char *p;
char buf[PATH_MAX];
Witch method is memory less use
PATH_MAX
snprintf(buf, sizeof(buf) - 1, "/dev/%s", p);
device = &buf[0];
or
asprintf
asprintf(&device, "/dev/%s", p);
asprintf allocates the memory needed dynamically while the first method declares a (probably) larger buffer on the stack. So asprintf uses exactly as much bytes as needed and char buf[MAX] does not. But you have to make sure you free the memory allocated in asprintf yourself
The most significant difference is not the few bytes of memory, but where the memory is coming from and how you need to handle it afterwards.
buf is allocated on the stack, and if you return from the function your snippet is coming from, then device will not point to a valid memory location anymore. Corruption or a crash will be the most likely outcome. On the other hand, if you only use device inside the function, you won't have to free it afterwards. Also, stack-allocated memory is more efficient in general, although caching and optimizations may equal the picture.
asprintf allocates the memory from the heap, which means you can safely pass it around to all parts of your program as long as it runs. The downside is that you have to free it when you don't need it anymore or it will hang around forever and you have a memory leak (which might matter or not, depending on how many unfreed buffers are floating around). It's then your responsibility to free the memory.
But to answer your question: asprintf will allocate no more bytes than needed, and you don't have to specify a maximum size which might "feel" better. You probably shouldn't worry about a few bytes of stack memory extra though. How big is PATH_MAX? Half a kilobyte?