Shrink dynamic arrays with delete[] operator

623 views
Skip to first unread message

con...@ncomputers.org

unread,
Oct 15, 2014, 1:47:38 PM10/15/14
to std-pr...@isocpp.org

Shrink dynamic arrays with delete[] operator


It is very useful to shrink arrays, which were created using the new operator.

For example:

A code requires a billion of objects of a class to find a solution to a hard problem. As the code finds a new and better solution, some objects will become useless. Due to complexity, the code starts to require more time to process the useful data and find better solutions.

As the code had a billion of useful objects in memory, it required only a few seconds to find a solution to the problem, because they were easier to find. When the code searches better solutions, it requires less objects and more time. For example, when it searches a solution with only one million of objects, it will delay a week to find a new and better solution to the problem.

It would be a waste of memory to have 999 millions of useless objects for a whole week. Just imagine, if every object requires ten bytes, the code will be wasting 9.99 billions of bytes for a whole week.

Thanks to the community of stackoverflow.com, cplusplus.com and its contributors, we considered two possible solutions to shrink arrays:
  • Allocate memory using the std::malloc function and shrink the array using the std::realloc function.
  • Create a new array, copy the useful objects and delete the old arrays.
Both are good solutions.

But we desire a solution, which is oriented to objects, automatically calls the destructors, is a C++ standard compatible with most memory allocators and neither moves the useful data nor copies it, due to performance.
  • To use the std::malloc and std::realloc functions is a solution, which requires to overload the new and delete operators to make it oriented to objects.
  • To create a new array, copy the useful objects and delete the old array is a solution, which would be very slow if we shrink the array a billion of times.
  • The performance offered by the std::vector when shrinking could be overcome by own implementations or native arrays.
Our suggestion to make arrays shrinkable in a C++ oriented to objects way is the following:
  • Improve the delete[] operator syntax by this way:

    delete [objects to delete] pointer to array;

    where delete[0] is equivalent to delete nothing.
We wrote the following partial solution to shrink arrays using an explicit call to an overloaded delete[] operator.

Examples: Shrinkable arrays vs vectors | Initialize undefined size arrays

/* author: ncomputers.org */
#include<cstdlib>
#include<iostream>
using namespace std;
 
 
void*operator new[](size_t s){
     
return malloc(s);
 
}
 
void operator delete[](void*p){
     free
(p);
 
}
 
void operator delete[](void*p,size_t s){
     
//It doesn't support objects with destructor.
     
if(realloc(p,s)!=p)throw 0;
 
}
 
 
int main(){
     
typedef int A;
     A
*a=new A[100];
     
//Suggested syntax:
     
//delete[90]a;
     
operator delete[](a,10*sizeof(A));
     
delete[]a;
     
return 0;
 
}

Best regards,

http://ncomputers.org

Joel Falcou

unread,
Oct 15, 2014, 2:15:16 PM10/15/14
to std-pr...@isocpp.org
why not using vector and resize or shrink_to_fit ?
handling raw memory using new/delete is usually ill advised in modern c++

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

con...@ncomputers.org

unread,
Oct 15, 2014, 2:30:47 PM10/15/14
to std-pr...@isocpp.org
Thank you very much for your time and your answer!


The performance offered by the std::vector when shrinking could be overcome by own implementations or native arrays.

It is probably due to: ISO/IEC JTC1/SC22/WG21 N3495

Best regards,

http://ncomputers.org 

Joel Falcou

unread,
Oct 15, 2014, 2:39:22 PM10/15/14
to std-pr...@isocpp.org
for such a benchmark to be valid it has to be done with a given replicable protocol. If not it's meaning less. So do you have a reproductible benchmark anybody can have a look at.
Abstarction penalty on std container is usually very low so I guess your benchmark is biased.

Joel Falcou

unread,
Oct 15, 2014, 2:41:35 PM10/15/14
to std-pr...@isocpp.org
it's in fact clearly biased as your timing on vector tim both the allcoation of the vector and of its contents ... Why don't you just create vector on the stack instaed of by using new ??

Bo Pesson

unread,
Oct 15, 2014, 2:45:30 PM10/15/14
to std-pr...@isocpp.org
On 2014-10-15 19:29, con...@ncomputers.org wrote:
>
> Shrink dynamic arrays on C++
>
>
> It is very useful to shrink arrays, which were created using the *new*
> operator.
>
> *For example:*
>
> Your code requires a billion of objects of a class to find a solution to
> a hard problem. As the code finds a new and better solution, some
> objects will become useless. Due to complexity, the code starts to
> require more time to process the useful data and find better solutions.
>
> As the code had a billion of useful objects in memory, it required only
> a few seconds to find a solution to the problem, because they were
> easier to find. When the code searches better solutions, it requires
> less objects and more time. For example, when it searches a solution
> with only one million of objects, it will delay a week to find a new and
> better solution to the problem.
>
> It would be a waste of memory to have 999 millions of useless objects
> for a whole week. Just imagine, if every object requires ten bytes, the
> code will be wasting 9.99 billions of bytes for a whole week.
>
> Thanks to the community of stackoverflow.com
> <http://www.stackoverflow.com>, cplusplus.com <http://www.cplusplus.com>
> and its contributors, we considered two possible solutions to shrink
> arrays:
>
> * Allocate memory using the *std::malloc* function and shrink the
> array using the *std::realloc* function.
> * Create a *new* array, copy the useful objects and *delete* the old
> arrays.
>
> Both are good solutions.
>
> But we desire a solution, which is oriented to objects, automatically
> calls the destructors, is a C++ standard compatible with most memory
> allocators and neither moves the useful data nor copies it, due to
> performance.
>
> * To use the *std::malloc* and *std::realloc* functions is a solution,
> which requires to overload the *new* and *delete* operators to make
> it oriented to objects.
> * To create a *new* array, copy the useful objects and *delete* the
> old array is a solution, which would be very slow if we shrink the
> array a billion of times.
> * The performance offered by the *std::vector* when shrinking could be
> overcome by other implementations or native arrays
> <http://ncomputers.org/content/code.php?src=examples/shrink%20arrays%201.cpp>.
>

I believe your calls to realloc(p, size-1) actually doesn't free up any
memory, which of course would be faster than shrinking the vector.


Bo Persson



con...@ncomputers.org

unread,
Oct 15, 2014, 2:48:04 PM10/15/14
to std-pr...@isocpp.org
it's in fact clearly biased as your timing on vector tim both the allcoation of the vector and of its contents ... Why don't you just create vector on the stack instaed of by using new ??

Because the number of vectors or arrays used by the code by one of our codes is undefined. It can vary with the time. The first second can be only 1, then 10, then 1,000, then 10, and so on.

Best regards,

http://ncomputers.org
 

con...@ncomputers.org

unread,
Oct 15, 2014, 3:02:32 PM10/15/14
to std-pr...@isocpp.org, b...@gmb.dk
Thank you very much for your time and your answer!

I invite you to watch memory usage running this code:

#include<cstdlib>
#include<stdio.h>

#include<iostream>
using namespace std;

void*operator new[](size_t s){
   
return malloc(s);
}
void operator delete[](void*p){
    free
(p);
}
void operator delete[](void*p,size_t s){

   
if(realloc(p,s)!=p)throw 0;
}

int main(){
   
unsigned s=1024,S=1024*1024*1024;
   
char*a=new char[S]();
    cout
<<S<<" bytes allocated and initialized, press any key to shrink array to "<<s<<" bytes"<<endl;
    getchar
();
   
operator delete[](a,s);
    cout
<<"Array shrunk to "<<s<<" bytes, press any key to delete it"<<endl;
    getchar
();
   
delete[]a;
   
return 0;
}

Best regards,

http://ncomputers.org

Farid Mehrabi

unread,
Oct 17, 2014, 3:09:07 PM10/17/14
to std-proposals
2014-10-15 22:11 GMT+03:30 Joel Falcou <joel....@gmail.com>:
it's in fact clearly biased as your timing on vector tim both the allcoation of the vector and of its contents ... Why don't you just create vector on the stack instaed of by using new ??

It is not biased, It is ill-formed.
The vector **has to** be placed on the stack because ***It is supposed to replace the raw pointer in the other code***.
I smell C# from this code.

Regards,
FM.

Farid Mehrabi

unread,
Oct 17, 2014, 3:24:45 PM10/17/14
to std-proposals
2014-10-15 22:18 GMT+03:30 <con...@ncomputers.org>:
it's in fact clearly biased as your timing on vector tim both the allcoation of the vector and of its contents ... Why don't you just create vector on the stack instaed of by using new ??

Because the number of vectors or arrays used by the code by one of our codes is undefined. It can vary with the time. The first second can be only 1, then 10, then 1,000, then 10, and so on.


I`m afraid your short answer does not look vivid to me; Can u plz discus in more details?

Regards,
FM.

con...@ncomputers.org

unread,
Oct 17, 2014, 7:21:15 PM10/17/14
to std-pr...@isocpp.org
Thank you very much for your time and your answer.

The code is inteded to compare both implementations when shrinking.

It is very strong related to this paper: n3495

I wrote these short codes to try to clarify it better, please consider that english is a foreign language for me and sometimes it is easier to me to express my point of view using codes, than words.

We create and delete the whole vector, beacuse these two reasons:
  1. The amount of vectors that the code will use is undefine during compile time.
  2. To call the constructor and the destructor of the objects is easier creating the whole vector and deleting it.
  3. Because we are comparing the performance when shrinking, we wrote the two test the most similiar we could, that means to use the new operator on both cases.
#include<iostream>
#include<vector>
using namespace std;

struct A{
    A
(){
        cout
<<"constructor"<<endl;
   
}
   
~A(){
        cout
<<"detructor"<<endl;
   
}
};

int main(){
   
delete new vector<A>(5);
}

As n3495 says, std::allocator lose the advantages offered realloc.

This code is intended to show a disadvantage of the fact previously mentioned. On some cases, rather when the performance is the main goal of a code, it could be better to use realloc than to use std::vector::shrink_to_fit, because it usualy moves the data, what is intended to decrease memory fragmentation, but when it is better to have a good performance than to avoid some fragmentation, realloc could be chosen as the best option. Obviously when the blocks are moved, the performance will decrease considerably.

#include<iostream>
#include<vector>
using namespace std;

int main(){
   
try{
       
unsigned S=1024;
        vector
<int>a(S);
       
for(unsigned s=S-1;s>0;--s){
           
int*b=&a[0];
            cout
<<b<<endl;
            a
.resize(s);
            a
.shrink_to_fit();
           
int*c=&a[0];
            cout
<<c<<endl;
           
if(b!=c){
               
throw "Data moved!";
           
}
       
}
        cout
<<"Data never moved"<<endl;
   
}
   
catch(char const*const& e){
        cout
<<e<<endl;
   
}
   
return 0;
}

Please note that what we're purposing is to allow the shrinking of arrays and even vectors without moving the data, what probably implies to add a new functionallity to std::allocator, that allows it.

I've tested realloc with glibc and it never moved the data. It is very useful to have the possibility to free some gigabytes when they became useles despite fragmentation.

#include<cstdlib>
#include<iostream>
using namespace std;

int main(){
   
try{
       
unsigned S=1024;
       
int*a=(int*)malloc(S*sizeof(int));
       
for(unsigned s=S-1;s>0;--s){
           
int*b=&a[0];
            cout
<<b<<endl;
            a
=(int*)realloc(a,s*sizeof(int));
           
int*c=&a[0];
            cout
<<c<<endl;
           
if(b!=c){
               
throw "Data moved!";
           
}
       
}
        free
(a);
        cout
<<"Data never moved"<<endl;
   
}
   
catch(char const*const& e){
        cout
<<e<<endl;
   
}
   
return 0;
}

Nevin Liber

unread,
Oct 18, 2014, 12:47:25 AM10/18/14
to std-pr...@isocpp.org
On 17 October 2014 18:21, <con...@ncomputers.org> wrote:
  1. The amount of vectors that the code will use is undefine during compile time.
So why not use a vector of vectors?
 
As n3495 says, std::allocator lose the advantages offered realloc.

realloc is a horrible interface that only works for things with trivial copy constructors.  To add a general grow/shrink in place facility may require replacing the entire malloc implementation to support it, which would be a much bigger proposal than n3495.
  
because it usualy moves the data,

No; it bitwise copies the data.
 
I've tested realloc with glibc and it never moved the data.

Well, yeah, because you do exactly *one* heap allocation in your program and then shrink the space; shrinking never has to move anything.  Not exactly a realistic test for most programs...

If all you are doing is using POD types (such as int), why not just use realloc and be done with it?
-- 
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

David Krauss

unread,
Oct 18, 2014, 1:15:18 AM10/18/14
to std-pr...@isocpp.org

On 2014–10–18, at 12:46 PM, Nevin Liber <ne...@eviloverlord.com> wrote:

realloc is a horrible interface that only works for things with trivial copy constructors.  To add a general grow/shrink in place facility may require replacing the entire malloc implementation to support it, which would be a much bigger proposal than n3495.

Really? I’d think the functionality could be sliced off any existing malloc. Anyway, if it’s not supported, just unconditionally return nullptr or whatever. (Er, really no “whatever." To be practical, it has to be a null return.)

There should be a generic interface for resizing allocations simply for the sake of custom allocators. If it’s something that many can do, then it should be represented by the common interface.

N3495 has issues but I’m surprised by the lack of follow-up. Also, N3495 looks completely different from the one proposal I recall with a C++ adaptation of realloc, which also had issues. So maybe I shouldn’t really be surprised. Maybe I’ll take a shot at it one day :P . But N3495 does hit most of the right notes.

con...@ncomputers.org

unread,
Oct 18, 2014, 1:19:32 AM10/18/14
to std-pr...@isocpp.org
Thank you very much for your time and your answer:


So why not use a vector of vectors?

One time someone made me the same question. So far my experiene says, when the amount of vectors is undefined during compile time, it will be always neccesary to use the new operator for each vector, despite it will be contained by other vector. Can you prove the contrary?


To add a general grow/shrink in place facility may require replacing the entire malloc implementation to support it,

I agree with you, that's what be are indirectly purposing.


No; it bitwise copies the data.

So far my knowledge says, to move data means: To copy first the data and then to delete, relase, free, etc. the old data, except when someone is talking about the movement of the physical storage of the data.


Well, yeah, because you do exactly *one* heap allocation in your program and then shrink the space; shrinking never has to move anything.  Not exactly a realistic test for most programs...

We ran a long time test, with a lot of arrays, with random sizes, which were shrunk to random sizes and the data was never moved. The goal of this purpose is to improve the std::allocator and delete[] operator to allow in place shrinking, which could offer great performance, not to standardize the usage of malloc, realloc and free.


If all you are doing is using POD types (such as int), why not just use realloc and be done with it?

I invite you to see this code, which we posted above as example. We understand your point and are also trying to make an overloaded delete[] operator, which allows in-place shrinking, to support objcts with destructors, all our tries and the tries of others couldn't achieve this, because of the need of an explicit call to the delete[] operator, what seen from our point of view, is another strong reason to improve the delete[] operator.


void*operator new[](size_t s){
   
return malloc(s);
}
void operator delete[](void*p){
    free
(p);
}
void operator delete[](void*p,size_t s){
   
//It doesn't support objects with destructor.
   
if(realloc(p,s)!=p)throw 0;
}

Best regards,

ncomputers.org

con...@ncomputers.org

unread,
Oct 18, 2014, 1:32:49 AM10/18/14
to std-pr...@isocpp.org
Quick correction:


To add a general grow/shrink in place facility may require replacing the entire malloc implementation to support it, which would be a much bigger proposal than n3495.

I agree with:


which would be a much bigger proposal than n3495.

We, think, that it is a bigger proposal than n3495.

It is n3495 + improvement to the delete[] operator.

I don't agree with this:


may require replacing the entire malloc implementation to support it

We want to use an std::allocator which supports inplace shrinking, not to use malloc. The codes written by us, that you can find on this topic, use malloc, realloc and free as example.

Best regards,

ncomputers.org

El viernes, 17 de octubre de 2014 23:47:25 UTC-5, Nevin ":-)" Liber escribió:

con...@ncomputers.org

unread,
Oct 18, 2014, 1:38:56 AM10/18/14
to std-pr...@isocpp.org
Thank you very much for your time and your answer!


I didn't understand exactly what you wrote:

I’d think the functionality could be sliced off any existing malloc.

I agree with this:

There should be a generic interface for resizing allocations simply for the sake of custom allocators. If it’s something that many can do, then it should be represented by the common interface.

I didn't understand this:


N3495 looks completely different from the one proposal I recall with a C++ adaptation of realloc, which also had issues.

Which porposal is "C++ adaptation of realloc"?

What did you want to express?


Maybe I’ll take a shot at it one day :P . But N3495 does hit most of the right notes.

David Krauss

unread,
Oct 18, 2014, 1:43:16 AM10/18/14
to std-pr...@isocpp.org
On 2014–10–18, at 1:38 PM, con...@ncomputers.org wrote:

Thank you very much for your time and your answer!

I didn't understand exactly what you wrote:

I’d think the functionality could be sliced off any existing malloc.

Nevin said that resizing malloc allocations would require a rewrite of malloc. I think that it would not be a total rewrite, but only an adaptation of code that should already exist for realloc. And anyway, it shouldn’t be a big deal when a platform doesn’t support it.

I didn't understand this:

N3495 looks completely different from the one proposal I recall with a C++ adaptation of realloc, which also had issues.

Which porposal is "C++ adaptation of realloc"?

What did you want to express?

Anything that provides a capability to change the size of an allocation without getting into realloc’s requirement of trivial copyability, I’d consider to be a C++ adaptation of realloc. There have been several, but I’m not digging for the others right now.

con...@ncomputers.org

unread,
Oct 18, 2014, 2:02:17 AM10/18/14
to std-pr...@isocpp.org
David, thank you very much for your answer!


it shouldn’t be a big deal when a platform doesn’t support it.

I agree with it.


 There have been several, but I’m not digging for the others right now.

I understand it. So far my experience says, it is easier to propose something new, than that the proposals become accepted. We're excepting that it could even require more than ten years,
that the std::allocator become standardized to allow in-place resizing.

One of our objectives is to share this idea for the improvement of the delete[] operator, so programmers around the world can know it and the right ones, will achieve to standardize such proposals or similars.

The codes that we're writting could free some megabytes of useless data and we're writting in them (commented):

//Awaiting shrinkable arrays:
delete [oldSize - newSize] pointer;

So, when shrinkable arrays are possible, someone will uncomment the lines and those megabytes of waste can be freed.

Unfortunately we don't have neither the necessary experience nor the time to write a paper, which has high possibilities to be accepted and standardized, but how do you think, that we can contribute to support every reasonable proposal of what you call:

C++ adaptation of realloc

And to make programmers consider the possibility of having a logical new[size] and delete[size] operators?

ncomputers.org

Nevin Liber

unread,
Oct 18, 2014, 2:24:02 AM10/18/14
to std-pr...@isocpp.org
On 18 October 2014 00:43, David Krauss <pot...@gmail.com> wrote:

Nevin said that resizing malloc allocations would require a rewrite of malloc. I think that it would not be a total rewrite, but only an adaptation of code that should already exist for realloc. And anyway, it shouldn’t be a big deal when a platform doesn’t support it.

But malloc is typically in the domain of C and the OS.  On some systems for instance, you can intercept the malloc calls and replace them.  It is not trivial to add a reallocate-in-place facility that remains compatible with all these real world malloc implementations.

To properly take advantage of this, you need to change vector, allocators and malloc.  Now, given that most programs interleave allocations made in different objects (think about a vector<string>, for instance), you then have to benchmark your implementation to show under what circumstances it is a clear win for adding all this complexity.

That's a lot of work.  Assuming the outcome is a performance win for adding reallocate-in-place, then you have a shot at a proposal being successful.

Nevin Liber

unread,
Oct 18, 2014, 2:37:15 AM10/18/14
to std-pr...@isocpp.org
On 18 October 2014 01:02, <con...@ncomputers.org> wrote:
I understand it. So far my experience says, it is easier to propose something new, than that the proposals become accepted. We're excepting that it could even require more than ten years,
that the std::allocator become standardized to allow in-place resizing.

std::allocator must call  ::operator new(std::size_t) to get space, so it has to be compatible with that.  Plus, it is extremely unlikely that making std::allocator having a different interface than other allocators would ever pass.
 
Unfortunately we don't have neither the necessary experience nor the time to write a paper,
-- 

David Krauss

unread,
Oct 18, 2014, 2:42:01 AM10/18/14
to std-pr...@isocpp.org
On 2014–10–18, at 2:23 PM, Nevin Liber <ne...@eviloverlord.com> wrote:

But malloc is typically in the domain of C and the OS.  On some systems for instance, you can intercept the malloc calls and replace them.  It is not trivial to add a reallocate-in-place facility that remains compatible with all these real world malloc implementations.

That’s why my suggestion is to focus on the generic Allocator concept, not on std::allocator.

To properly take advantage of this, you need to change vector, allocators and malloc.  Now, given that most programs interleave allocations made in different objects (think about a vector<string>, for instance), you then have to benchmark your implementation to show under what circumstances it is a clear win for adding all this complexity.

You can get phenomenal performance by tuning a program to use a few string arenas without interleaving. The bytes recovered by an eager shrink-to-fit operation on the last allocation are going to be in L1 cache, and they’re the next to get allocated.

How much improvement to everyday programs, when shrink-to-fit is enabled with malloc? Maybe not much. But that’s only one side of the argument. It’s still worthwhile to enable better performance in fast allocators with proper support. Right now, the allocator gets coupled unnecessarily to the algorithm because this one generic interface is missing.

Nevin Liber

unread,
Oct 18, 2014, 2:57:49 AM10/18/14
to std-pr...@isocpp.org
On 18 October 2014 01:41, David Krauss <pot...@gmail.com> wrote:

You can get phenomenal performance by tuning a program to use a few string arenas without interleaving. The bytes recovered by an eager shrink-to-fit operation on the last allocation are going to be in L1 cache, and they’re the next to get allocated.

Oh, sure.
 

How much improvement to everyday programs, when shrink-to-fit is enabled with malloc? Maybe not much. But that’s only one side of the argument. It’s still worthwhile to enable better performance in fast allocators with proper support. Right now, the allocator gets coupled unnecessarily to the algorithm because this one generic interface is missing.

You cannot say it is worthwhile until you've actually measured it.

All I'm saying is that it is a lot of work to do to get it to a point where a proposal has a decent chance of succeeding (IMHO).  If you are volunteering to do it, I say go for it!

David Krauss

unread,
Oct 18, 2014, 3:08:40 AM10/18/14
to std-pr...@isocpp.org
On 2014–10–18, at 2:57 PM, Nevin Liber <ne...@eviloverlord.com> wrote:

On 18 October 2014 01:41, David Krauss <pot...@gmail.com> wrote:

You can get phenomenal performance by tuning a program to use a few string arenas without interleaving. The bytes recovered by an eager shrink-to-fit operation on the last allocation are going to be in L1 cache, and they’re the next to get allocated.

Oh, sure.
 

How much improvement to everyday programs, when shrink-to-fit is enabled with malloc? Maybe not much. But that’s only one side of the argument. It’s still worthwhile to enable better performance in fast allocators with proper support. Right now, the allocator gets coupled unnecessarily to the algorithm because this one generic interface is missing.

You cannot say it is worthwhile until you've actually measured it.

I’m only saying that such parsing/generation strategies already exist (as you seem to acknowledge) and the library should encourage the allocator to be factored apart from the handling of content.

All I'm saying is that it is a lot of work to do to get it to a point where a proposal has a decent chance of succeeding (IMHO).  If you are volunteering to do it, I say go for it!

I guess it’ll go into the queue :P

Hopefully someone else will attempt, they’ll post here first, and I’ll influence them not to be too ambitious or specific but to prioritize the essentials.

con...@ncomputers.org

unread,
Oct 18, 2014, 3:13:04 AM10/18/14
to std-pr...@isocpp.org
David,


That’s why my suggestion is to focus on the generic Allocator concept, not on std::allocator.

Is std::allocator the responsable of allocate memory with the new operator? Or is the "generic allocator" that you mention?

May I know better how would this interface be?


It’s still worthwhile to enable better performance in fast allocators with proper support.

I agree with you. I think that, fast allocators search better performance.

http://ncomputers.org

David Krauss

unread,
Oct 18, 2014, 3:23:09 AM10/18/14
to std-pr...@isocpp.org
On 2014–10–18, at 3:13 PM, con...@ncomputers.org wrote:

David,

That’s why my suggestion is to focus on the generic Allocator concept, not on std::allocator.

Is std::allocator the responsable of allocate memory with the new operator? Or is the "generic allocator" that you mention?

std::allocator calls (specifically) ::operator new calls (in practice) malloc.

May I know better how would this interface be?

Anyone can write a custom allocator, following the rules of [allocator.requirements] §17.6.3.5. It will only be used when specifically instantiated, never by the default std::string, std::vector<T>, etc.

It’s still worthwhile to enable better performance in fast allocators with proper support.

I agree with you. I think that, fast allocators search better performance.

Custom allocators improve performance at a huge cost in convenience :/ . As I mentioned to Nevin, my take on this issue isn’t really about improving performance of existing programs, but to improve portability and modularity of certain program architectures. Maybe even help bring high-performance libraries to the masses, but still, porting a program to use custom allocators is a major hurdle which isn’t going away.

con...@ncomputers.org

unread,
Oct 18, 2014, 3:46:41 AM10/18/14
to std-pr...@isocpp.org
Hopefully someone else will attempt, they’ll post here first, and I’ll influence them not to be too ambitious or specific but to prioritize the essentials.

Yes someone will attempt it! I've talked about it with my team. If we had more free time, we would start to write it together just now! Unfortunately we don't have enough time and it would be the first paper for the ISO/ANSI C++, which I wrote, but I can learn a lot of you, collect the enough experience and especially, to learn how to argue front the committee to make the proposal to have success :D I'll also rejoice, if I find someone who wants to work together to achieve this standardization.

Seen from my point of view, it is obvious that a new[size] operator should have a delete[size] operator as counterpart.


std::allocator calls (specifically) ::operator new calls (in practice) malloc.

A professor taught me that the new operator only use malloc with glibc :(


Custom allocators improve performance at a huge cost in convenience :/ . As I mentioned to Nevin, my take on this issue isn’t really about improving performance of existing programs, but to improve portability and modularity of certain program architectures. Maybe even help bring high-performance libraries to the masses, but still, porting a program to use custom allocators is a major hurdle which isn’t going away.

I understand it. Our goal is to allow to shrink arrays allocated by the new operator and that every compiler support it.


 std::allocator calls (specifically) ::operator new calls (in practice) malloc.

If the ::operator new  calls (in practice) malloc, is it theoretically possible to use realloc?

We've used realloc for arrays allocated by the new operator, it works with glibc - GCC and Visual C++, but someone told us, that it is disallowed. Is it?

Other fact that is important to mention, is that the only possible way to call an overloaded delete[] operator with specific arguments is calling it explicitly, what causes to make very hard (or even impossible) to support objects with destructors, as described below.

That's why we suggest this improvement to the delete[] operator.
At least it should accept a call like the following, what is the same what we purpose:

delete (argument) [] pointer;

Additional information (Can someone answer one of the questions?):

We're trying to overload the delete[] operator to achieve shrinkable oriented to objects arrays.

It works fine with data types without specific destructor.

When the data type has a specified destructor, the new[] operator needs extra bytes.

Could you help us please to answer these questions?

  1. Why does the new[] operator require extra bytes for data types with specific destructor?
  2. Will always the new[] operator request these bytes or is it library dependent?
  3. Is it possible to know if the data type has a specific destructor with an if statement?

The code should throw an unhandled exception when it tries to shrink the array of B's.

#include<cstdlib>
#include<iostream>
using namespace std;

void*operator new[](size_t s){
    cout
<<"Block size: "<<s<<endl;

   
return malloc(s);
}
void operator delete[](void*p){
    free
(p);
}
void operator delete[](void*p,size_t s){

   
//Is it possible to know if the data type has a specific destructor?
   
bool destructor=0;
   
if(destructor){
        p
=(char*)p-8,s+=8;
   
}
    cout
<<"New block size: "<<s<<endl;
   
if(realloc(p,s)!=p)throw 0;
}

struct A{
   
char a;

    A
():a(0){}
   
~A()=default;
};

struct B{
   
char b;

    B
():b(0){}
   
~B(){}
};

int main(){
   
unsigned S=10,s=4;
    cout
<<"Creating "<<S<<" A's"<<endl;
    A
*a=new A[S];
    cout
<<"Creating "<<S<<" B's"<<endl;
    B
*b=new B[S];
    cout
<<"Shrinking A to "<<s<<" elements"<<endl;
   
operator delete[](a,sizeof(A)*s);
    cout
<<"Shrinking B to "<<s<<" elements"<<endl;
   
operator delete[](b,sizeof(B)*s);
    cout
<<"Deleting A and B"<<endl;
   
delete[]b,delete[]a;
   
return 0;
}


Farid Mehrabi

unread,
Oct 20, 2014, 2:40:55 PM10/20/14
to std-proposals
IMHO developing your own allocator/container system is  better and easier than trying to change the behavior of new/delete; It is already complicated enough and if not for the sake of existing libs and codes relying on new/delete, I wouldn't use them except for the case of placement new. The new/delete predate templates and therefor lack proper facilities to store customized run-time type info.
IMHO variadic templates and constructor forwarding, facilitate deriving tools that encourage deprecation of naked use of new/delete.
Someday when you get the opportunity to refactor/optimize your personal lib, a good proposal becomes possible. It takes more time but less risk.

regard,
FM.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.


--
how am I supposed to end the twisted road of  your hair in the dark night??
unless the candle of your face does turn a lamp up on my way!!!

con...@ncomputers.org

unread,
Oct 20, 2014, 3:15:20 PM10/20/14
to std-pr...@isocpp.org
Thank you very much for your comment.


Someday when you get the opportunity to refactor/optimize your personal lib, a good proposal becomes possible. It takes more time but less risk.

This is a very good recommendation. Thank you for helping us!

I am trying to have an overloaded delete[] operator that accepts specific arguments. Because the only way to call a delete[] operator with specific arguments is explicitly, it loses the support for objects with destructor. I've almost achieved personal shrinkable arrays. This is the last complication I have. Do you have any idea of how can we enable a sugar syntactic call to an overloaded delete[] operator with specific arguments: delete (argument)[] pointer like its counterpart new (argument)[size]?

Farid Mehrabi

unread,
Oct 21, 2014, 11:17:50 AM10/21/14
to std-proposals
2014-10-20 22:45 GMT+03:30 <con...@ncomputers.org>:
I am trying to have an overloaded delete[] operator that accepts specific arguments. Because the only way to call a delete[] operator with specific arguments is explicitly, it loses the support for objects with destructor. I've almost achieved personal shrinkable arrays. This is the last complication I have. Do you have any idea of how can we enable a sugar syntactic call to an overloaded delete[] operator with specific arguments: delete (argument)[] pointer like its counterpart new (argument)[size]?


if you still insist on overloading new - which is too tricky a choice - , just define a template function that explicitly destructs the object pointed to by its args right before calling a deleter routine on it. for more details just take a look into the implementation of std::vector and std::allocator. One downside to this approach is that in case constructors of the allocated objects should throw, clean up must be handled manually.  It is for this reason that IMHO one had better develop a container/allocator lib rather than trying to play with global new/delete.

regards,
FM.
 

con...@ncomputers.org

unread,
Oct 21, 2014, 1:20:44 PM10/21/14
to std-pr...@isocpp.org
Farid:

Thank you very much for your answers! You are helping me a lot!


take a look into the implementation of std::vector and std::allocator

Ok, I will do it.

Best Regards,

PF, ncomputers.org 

Farid Mehrabi

unread,
Oct 21, 2014, 2:02:33 PM10/21/14
to std-proposals
u r welcome. I am sorry; I should find a way of dropping that affirmative tone from my tongue(hand????), and make more use of  'plz' and 'one might'.
--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

con...@ncomputers.org

unread,
Oct 23, 2014, 2:24:25 PM10/23/14
to std-pr...@isocpp.org
I should find a way of dropping that affirmative tone from my tongue(hand????), and make more use of  'plz' and 'one might'.

I think that you are kind enough.
 
Reply all
Reply to author
Forward
0 new messages