Avoid memory allocations for formatting paths [closed] - c

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?

Related

Automatic vs dynamic memory allocation: what to consider? [closed]

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.

what happens in linux glibc if keep increasingly accessing memory exceeding malloc() allocated size [closed]

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.

Is memory malloc() through mmap() returned to OS immediately after calling free()? [closed]

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 6 years ago.
Improve this question
Is memory malloc() through mmap() returned to OS immediately after calling free()?
According to http://man7.org/linux/man-pages/man3/mallopt.3.html
For allocations greater than or equal to the limit specified (in
bytes) by M_MMAP_THRESHOLD that can't be satisfied from the free list,
the memory-allocation functions employ mmap(2) instead of increasing
the program break using sbrk(2).
Allocating memory using mmap(2) has the significant advantage that the
allocated memory blocks can always be independently released back to
the system. (By contrast, the heap can be trimmed only if memory is
freed at the top end.) On the other hand, there are some
disadvantages to the use of mmap(2): deallocated space is not placed
on the free list for reuse by later allocations;
So the large allocations which should be done with help of mmap, has nothing to do with malloc's list of free or used blocks, and they're come back to system when freed.
Be aware that mmap is a system call which might be quite expensive. malloc implementations take care to avoid calling it too often, that is why they manage previously free-d zones to reuse them later (in further malloc-s) without any syscall. In practice, most malloc implementations manage differently big allocations (e.g. more than a megabyte), which are often mmap-ed at malloc and munmap-ed at free time.
mmap-ed at malloc, memory is immediately returned to the OS, when you do free (internal munmap).
You could study the source code of some malloc.

malloc() in C not working as expected

I'm new to C. Sorry if this has already been answered, I could'n find a straight answer, so here we go..
I'm trying to understand how malloc() works in C. I have this code:
#define MAXLINE 100
void readInput(char **s)
{
char temp[MAXLINE];
printf("Please enter a string: ");
scanf("%s", temp);
*s = (char *)malloc((strlen(temp)+1)*sizeof(char)); // works as expected
//*s = (char *)malloc(2*sizeof(char)); // also works even when entering 10 chars, why?
strcpy ((char *)*s, temp);
}
int main()
{
char *str;
readInput(&str);
printf("Your string is %s\n", str);
free(str);
return 0;
}
The question is why doesn't the program crash (or at least strip the remaining characters) when I call malloc() like this:
*s = (char *)malloc(2*sizeof(char)); // also works even when entering 10 chars, why?
Won't this cause a buffer overflow if I enter a string with more than two characters? As I understood malloc(), it allocates a fixed space for data, so surely allocating the space for only two chars would allow the string to be maximum of one usable character ('0\' being the second), but it still is printing out all the 10 chars entered.
P.S. I'm using Xcode if that makes any difference.
Thanks,
Simon
It works out fine because you're lucky! Usually, a block a little larger than just 2 bytes is given to your program by your operating system.
If the OS actually gave you 16 bytes when you asked for 2 bytes, you could write 16 bytes without the OS taking notice of it. However if you had another malloc() in your program which used the other 14 bytes, you would write over that variables content.
The OS doesn't care about you messing about inside your own program. Your program will only crash if you write outside what the OS has given you.
Try to write 200 bytes and see if it crashes.
Edit:
malloc() and free() uses some of the heap space to maintain information about allocated memory. This information is usually stored in between the memory blocks. If you overflow a buffer, this information may get overwritten.
Yes writing more data into an allocated buffer is a buffer overflow. However there is no buffer overflow check in C and if there happens to be valid memory after your buffer than your code will appear to work correctly.
However what you have done is write into memory that you don't own and likely have corrupted the heap. Your next call to free or malloc will likely crash, or if not the next call, some later call could crash, or you could get lucky and malloc handed you a larger buffer than you requested, in which case you'll never see an issue.
Won't this cause a buffer overflow if I enter a string with more than two characters?
Absolutely. However, C does no bounds checking at runtime; it assumes you knew what you were doing when you allocated the memory, and that you know how much is available. If you go over the end of the buffer, you will clobber whatever was there before.
Whether that causes your code to crash or not depends on what was there before and what you clobbered it with. Not all overflows will kill your program, and overflow in the heap may not cause any (obvious) problems at all.
This is because even if you did not allocate the memory, the memory exists.
You are accessing data that is not yours, and probably that with a good debugger, or static analyzer you would have seen the error.
Also if you have a variable that is just behind the block you allocated it will probably be overriden by what you enter.
Simply this is one of the case of undefined behavior. You are unlucky that you are getting the expected result.
It does cause a buffer overflow. But C doesn’t do anything to prevent a buffer overflow. Neither do most implementations of malloc.
In general, a crash from a buffer overflow only occurs when...
It overflows a page—the unit of memory that malloc actually gets from the operating system. Malloc will fulfill many individual allocation requests from the same page of memory.
The overflow corrupts the memory that follows the buffer. This doesn’t cause an immediate crash. It causes a crash later when other code runs that depends upon the contents of that memory.
(...but these things depend upon the specifics of the system involved.)
It is entirely possible, if you are lucky, that a buffer overflow will never cause a crash. Although it may create other, less noticeable problems.
malloc() is the function call which is specified in Stdlib.h header file. If you are using arrays, you have to fix your memory length before utilize it. But in malloc() function, you can allocate the memory when you need and in required size. When you allocate the memory through malloc() it will search the memory modules and find the free block. even the memory blocks are in different places, it will assign a address and connect all the blocks.
when your process finish, you can free it. Free means, assigning a memory is in RAM only. once you process the function and make some data, you will shift the data to hard disk or any other permenant storage. afterwards, you can free the block so you can use for another data.
If you are going through pointer function, with out malloc() you can not make data blocks.
New() is the keyword for c++.
When you don't know when you are programming how big is the space of memory you will need, you can use the function malloc
void *malloc(size_t size);
The malloc() function shall allocate unused space for an object whose size in bytes is specified by size and whose value is unspecified.
how does it work is the question...
so
your system have the free chain list, that lists all the memory spaces available, the malloc search this list until it finds a space big enough as you required. Then it breaks this space in 2, sends you the space you required and put the other one back in the list. It breaks in pieces of size 2^n that way you wont have weird space sizes in your list, what makes it easy just like Lego.
when you call 'free' your block goes back to the free chain list.

allocating memory sequencially in C [closed]

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.

Resources