Defining realloc () behavior before calling

As I understand it, when requesting to reserve a large block of memory, the realloc () function will perform one of three different tasks:

 if free contiguous block exists grow current block else if sufficient memory allocate new memory copy old memory to new free old memory else return null 

Growing the current block is a very cheap operation, so this is the behavior I would like to use. However, if I reallocate the memory because I want to (for example) insert a char at the beginning of an existing line, I do not want realloc () to copy the memory. I will finish copying the entire string with realloc (), and then copy it manually again to free the first element of the array.

Is it possible to determine what realloc () will do? If so, is it possible to achieve the cross-platform way?

+6
c memory-management
source share
8 answers

realloc() behavior probably depends on its specific implementation. And, basing your code on this, there will be a terrible hack that at least breaks encapsulation.

The best solution for your specific example:

  • Find the size of the current buffer
    • Highlight a new buffer (with malloc() ) larger than the previous one
    • Copy the prefix to the new buffer
    • Copy the line in the previous buffer to the new buffer, starting with the prefix
    • Release the previous buffer
+7
source share

As noted in the comments, case 3 in the question (without memory) is erroneous; realloc() will return NULL if there is no memory available [question is now fixed].

Steve McConnell in "Code Complete" indicates that if you store the return value from realloc() in a single copy of the original pointer, when realloc() fails, you simply skipped memory. I.e:

 void *ptr = malloc(1024); ... if ((ptr = realloc(ptr, 2048)) == 0) { /* Oops - cannot free original memory allocation any more! */ } 

Different realloc () implementations will behave differently. The only thing that can be assumed is that the data will always be moved - you will always receive a new address when the memory is reloaded.

As someone else remarked, if this bothers you, maybe it's time to look at your algorithms.

+2
source share

Will keep your trackback back?

Otherwise ... just malloc () has more space than you need, and when you run out of space, copy it to a new buffer. A simple method is to double the space each time; this works very well, because the larger the line (i.e. the more time it is copied to the new buffer), the less often this should happen.

Using this method, you can also correctly justify your string in the buffer, so it's easy to add characters to the beginning.

+1
source share

No - and if you think about it, he will not be able to work. Meanwhile, you check what it is going to do and actually does, another process may allocate memory. In a multi-threaded application this will not work. Between you check that she is going to do and actually does it, another thread can allocate memory.

If you are worried about this, it may be time to take a look at the data structures that you use to see if you can fix the problem. Depending on how these lines are constructed, you can do this quite efficiently with a well-designed buffer.

0
source share

I do not think this is possible on a cross-platform path. Here is the code for implementing ulibc that can give you an idea of ​​how to make this platform-dependent, it is actually better to find the source of glibc, but this one was on top of google search :)

0
source share

If obstacks are a good choice for your memory allocation needs, you can use their fast-growing functionality. Locks is a glibc function, but they are also available in the libiberty library, which is quite portable.

0
source share

Why not save the empty buffer space on the left side of the line, for example:

 char* buf = malloc(1024); char* start = buf + 1024 - 3; start[0]='t'; start[1]='o'; start[2]='\0'; 

To add "on" to the beginning of a line to make it "to \ 0":

 start-=2; if(start < buf) DO_MEMORY_STUFF(start, buf);//time to reallocate! start[0]='o'; start[1]='n'; 

Thus, you do not have to constantly copy your buffer every time you want to make input at the beginning.

If you need to make inserts both at the beginning and at the end, just select some space at both ends; inserts in the middle will still require you to randomly mix elements around.

0
source share

The best approach is to use a linked list. Select each of your data objects on the page and select another page and get a link to it either from the previous page or from the index page. This way, you know when the next call does not work, and you do not need to copy the memory.

0
source share

All Articles