Getting size of dynamic C-style array vs. use of delete[]. Contradiction? [duplicate]












25
















This question already has an answer here:




  • C++ doesn't tell you the size of a dynamic array. But why?

    7 answers




I read everywhere that in C++ it is not possible to get the size of a dynamic array just from the pointer pointing to that chunk of memory.



How is it possible that there is no way of getting the size of a dynamic array just from the pointer, and at the same time it is possible to free all the memory allocated by using delete just on the pointer, without the need of specifying the array size?



delete must know the size of the array, right? Therefore this information must exist somewhere. Shouldn't it?



What is wrong in my reasoning?










share|improve this question















marked as duplicate by Ben Voigt c++
Users with the  c++ badge can single-handedly close c++ questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
18 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • 7





    The underlying memory allocator knows the size of blocks it allocates, but there's no standard function that returns that information. There are sometimes non-standard malloc implementation specific ways but they're inherently non portable.

    – Shawn
    yesterday








  • 5





    Why is this ever interesting? Use std::vector and never worry about delete.

    – n.m.
    yesterday






  • 20





    @n.m. I don't get answers that tell you "don't bother". If one asks a question, there are reasons behind it. And the reasons don't have necessarily to be "practical reasons". It might be curiosity, it might be that I want to implement a compiler in machine code, or whatever. Even if we suppose one should always be backed by practical reasons in order to ask questions, I'm sure it is always possible to come up with at least one or two cases in which new knowledge could be used. There might be cases in which I cannot or don't want to use STL.

    – Michele Piccolini
    yesterday






  • 3





    "If one asks a question, there are reasons behind it." These reasons are not necessarily valid. If you want to learn how to use C++ efficiently then not bothering with delete and pointers is the right thing. They are too low level and there are gazillion of these low level things of zero importance. Trying to learn them all is a waste of time. If you are in a situation where you cannot use std::vector (which should be extremely rare) you might want to look inside a typical implementation to learn how it works in order to replicate some of it.

    – n.m.
    yesterday






  • 12





    @n.m. I don't think SO is limited to people "learning how to use C++ efficiently". Otherwise the language-lawyer tag would be pretty useless. Someone has to deal with all these "low level things", so why is asking about them on SO unreasonable?

    – Max Langhof
    yesterday
















25
















This question already has an answer here:




  • C++ doesn't tell you the size of a dynamic array. But why?

    7 answers




I read everywhere that in C++ it is not possible to get the size of a dynamic array just from the pointer pointing to that chunk of memory.



How is it possible that there is no way of getting the size of a dynamic array just from the pointer, and at the same time it is possible to free all the memory allocated by using delete just on the pointer, without the need of specifying the array size?



delete must know the size of the array, right? Therefore this information must exist somewhere. Shouldn't it?



What is wrong in my reasoning?










share|improve this question















marked as duplicate by Ben Voigt c++
Users with the  c++ badge can single-handedly close c++ questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
18 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.














  • 7





    The underlying memory allocator knows the size of blocks it allocates, but there's no standard function that returns that information. There are sometimes non-standard malloc implementation specific ways but they're inherently non portable.

    – Shawn
    yesterday








  • 5





    Why is this ever interesting? Use std::vector and never worry about delete.

    – n.m.
    yesterday






  • 20





    @n.m. I don't get answers that tell you "don't bother". If one asks a question, there are reasons behind it. And the reasons don't have necessarily to be "practical reasons". It might be curiosity, it might be that I want to implement a compiler in machine code, or whatever. Even if we suppose one should always be backed by practical reasons in order to ask questions, I'm sure it is always possible to come up with at least one or two cases in which new knowledge could be used. There might be cases in which I cannot or don't want to use STL.

    – Michele Piccolini
    yesterday






  • 3





    "If one asks a question, there are reasons behind it." These reasons are not necessarily valid. If you want to learn how to use C++ efficiently then not bothering with delete and pointers is the right thing. They are too low level and there are gazillion of these low level things of zero importance. Trying to learn them all is a waste of time. If you are in a situation where you cannot use std::vector (which should be extremely rare) you might want to look inside a typical implementation to learn how it works in order to replicate some of it.

    – n.m.
    yesterday






  • 12





    @n.m. I don't think SO is limited to people "learning how to use C++ efficiently". Otherwise the language-lawyer tag would be pretty useless. Someone has to deal with all these "low level things", so why is asking about them on SO unreasonable?

    – Max Langhof
    yesterday














25












25








25


1







This question already has an answer here:




  • C++ doesn't tell you the size of a dynamic array. But why?

    7 answers




I read everywhere that in C++ it is not possible to get the size of a dynamic array just from the pointer pointing to that chunk of memory.



How is it possible that there is no way of getting the size of a dynamic array just from the pointer, and at the same time it is possible to free all the memory allocated by using delete just on the pointer, without the need of specifying the array size?



delete must know the size of the array, right? Therefore this information must exist somewhere. Shouldn't it?



What is wrong in my reasoning?










share|improve this question

















This question already has an answer here:




  • C++ doesn't tell you the size of a dynamic array. But why?

    7 answers




I read everywhere that in C++ it is not possible to get the size of a dynamic array just from the pointer pointing to that chunk of memory.



How is it possible that there is no way of getting the size of a dynamic array just from the pointer, and at the same time it is possible to free all the memory allocated by using delete just on the pointer, without the need of specifying the array size?



delete must know the size of the array, right? Therefore this information must exist somewhere. Shouldn't it?



What is wrong in my reasoning?





This question already has an answer here:




  • C++ doesn't tell you the size of a dynamic array. But why?

    7 answers








c++ arrays heap






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday









Peter Mortensen

13.7k1986111




13.7k1986111










asked yesterday









Michele PiccoliniMichele Piccolini

429210




429210




marked as duplicate by Ben Voigt c++
Users with the  c++ badge can single-handedly close c++ questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
18 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.









marked as duplicate by Ben Voigt c++
Users with the  c++ badge can single-handedly close c++ questions as duplicates and reopen them as needed.

StackExchange.ready(function() {
if (StackExchange.options.isMobile) return;

$('.dupe-hammer-message-hover:not(.hover-bound)').each(function() {
var $hover = $(this).addClass('hover-bound'),
$msg = $hover.siblings('.dupe-hammer-message');

$hover.hover(
function() {
$hover.showInfoMessage('', {
messageElement: $msg.clone().show(),
transient: false,
position: { my: 'bottom left', at: 'top center', offsetTop: -7 },
dismissable: false,
relativeToBody: true
});
},
function() {
StackExchange.helpers.removeMessages();
}
);
});
});
18 hours ago


This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.










  • 7





    The underlying memory allocator knows the size of blocks it allocates, but there's no standard function that returns that information. There are sometimes non-standard malloc implementation specific ways but they're inherently non portable.

    – Shawn
    yesterday








  • 5





    Why is this ever interesting? Use std::vector and never worry about delete.

    – n.m.
    yesterday






  • 20





    @n.m. I don't get answers that tell you "don't bother". If one asks a question, there are reasons behind it. And the reasons don't have necessarily to be "practical reasons". It might be curiosity, it might be that I want to implement a compiler in machine code, or whatever. Even if we suppose one should always be backed by practical reasons in order to ask questions, I'm sure it is always possible to come up with at least one or two cases in which new knowledge could be used. There might be cases in which I cannot or don't want to use STL.

    – Michele Piccolini
    yesterday






  • 3





    "If one asks a question, there are reasons behind it." These reasons are not necessarily valid. If you want to learn how to use C++ efficiently then not bothering with delete and pointers is the right thing. They are too low level and there are gazillion of these low level things of zero importance. Trying to learn them all is a waste of time. If you are in a situation where you cannot use std::vector (which should be extremely rare) you might want to look inside a typical implementation to learn how it works in order to replicate some of it.

    – n.m.
    yesterday






  • 12





    @n.m. I don't think SO is limited to people "learning how to use C++ efficiently". Otherwise the language-lawyer tag would be pretty useless. Someone has to deal with all these "low level things", so why is asking about them on SO unreasonable?

    – Max Langhof
    yesterday














  • 7





    The underlying memory allocator knows the size of blocks it allocates, but there's no standard function that returns that information. There are sometimes non-standard malloc implementation specific ways but they're inherently non portable.

    – Shawn
    yesterday








  • 5





    Why is this ever interesting? Use std::vector and never worry about delete.

    – n.m.
    yesterday






  • 20





    @n.m. I don't get answers that tell you "don't bother". If one asks a question, there are reasons behind it. And the reasons don't have necessarily to be "practical reasons". It might be curiosity, it might be that I want to implement a compiler in machine code, or whatever. Even if we suppose one should always be backed by practical reasons in order to ask questions, I'm sure it is always possible to come up with at least one or two cases in which new knowledge could be used. There might be cases in which I cannot or don't want to use STL.

    – Michele Piccolini
    yesterday






  • 3





    "If one asks a question, there are reasons behind it." These reasons are not necessarily valid. If you want to learn how to use C++ efficiently then not bothering with delete and pointers is the right thing. They are too low level and there are gazillion of these low level things of zero importance. Trying to learn them all is a waste of time. If you are in a situation where you cannot use std::vector (which should be extremely rare) you might want to look inside a typical implementation to learn how it works in order to replicate some of it.

    – n.m.
    yesterday






  • 12





    @n.m. I don't think SO is limited to people "learning how to use C++ efficiently". Otherwise the language-lawyer tag would be pretty useless. Someone has to deal with all these "low level things", so why is asking about them on SO unreasonable?

    – Max Langhof
    yesterday








7




7





The underlying memory allocator knows the size of blocks it allocates, but there's no standard function that returns that information. There are sometimes non-standard malloc implementation specific ways but they're inherently non portable.

– Shawn
yesterday







The underlying memory allocator knows the size of blocks it allocates, but there's no standard function that returns that information. There are sometimes non-standard malloc implementation specific ways but they're inherently non portable.

– Shawn
yesterday






5




5





Why is this ever interesting? Use std::vector and never worry about delete.

– n.m.
yesterday





Why is this ever interesting? Use std::vector and never worry about delete.

– n.m.
yesterday




20




20





@n.m. I don't get answers that tell you "don't bother". If one asks a question, there are reasons behind it. And the reasons don't have necessarily to be "practical reasons". It might be curiosity, it might be that I want to implement a compiler in machine code, or whatever. Even if we suppose one should always be backed by practical reasons in order to ask questions, I'm sure it is always possible to come up with at least one or two cases in which new knowledge could be used. There might be cases in which I cannot or don't want to use STL.

– Michele Piccolini
yesterday





@n.m. I don't get answers that tell you "don't bother". If one asks a question, there are reasons behind it. And the reasons don't have necessarily to be "practical reasons". It might be curiosity, it might be that I want to implement a compiler in machine code, or whatever. Even if we suppose one should always be backed by practical reasons in order to ask questions, I'm sure it is always possible to come up with at least one or two cases in which new knowledge could be used. There might be cases in which I cannot or don't want to use STL.

– Michele Piccolini
yesterday




3




3





"If one asks a question, there are reasons behind it." These reasons are not necessarily valid. If you want to learn how to use C++ efficiently then not bothering with delete and pointers is the right thing. They are too low level and there are gazillion of these low level things of zero importance. Trying to learn them all is a waste of time. If you are in a situation where you cannot use std::vector (which should be extremely rare) you might want to look inside a typical implementation to learn how it works in order to replicate some of it.

– n.m.
yesterday





"If one asks a question, there are reasons behind it." These reasons are not necessarily valid. If you want to learn how to use C++ efficiently then not bothering with delete and pointers is the right thing. They are too low level and there are gazillion of these low level things of zero importance. Trying to learn them all is a waste of time. If you are in a situation where you cannot use std::vector (which should be extremely rare) you might want to look inside a typical implementation to learn how it works in order to replicate some of it.

– n.m.
yesterday




12




12





@n.m. I don't think SO is limited to people "learning how to use C++ efficiently". Otherwise the language-lawyer tag would be pretty useless. Someone has to deal with all these "low level things", so why is asking about them on SO unreasonable?

– Max Langhof
yesterday





@n.m. I don't think SO is limited to people "learning how to use C++ efficiently". Otherwise the language-lawyer tag would be pretty useless. Someone has to deal with all these "low level things", so why is asking about them on SO unreasonable?

– Max Langhof
yesterday












5 Answers
5






active

oldest

votes


















27














TL;DR The operator delete destructs the objects and deallocates the memory. The information N ("number of elements") is required for destructing. The information S ("size of allocated memory") is required for deallocating. S is always stored and can be queried by compiler extensions. N is only stored if destructing objects requires calling destructors. If N is stored, where it is stored is implementation-dependent.





The operator delete has to do two things:



a) destructing the objects (calling destructors, if necessary) and



b) deallocating the memory.



Let's first discuss (de)allocation, which
is delegated to the C functions malloc and free by many compilers (like GCC). The function malloc takes the number of bytes to be allocated as a parameter and returns a pointer. The function free takes only a pointer; the number of bytes is not necessary. This means that the memory allocating functions have to keep track how many bytes have been allocated. There could be a function to query how many bytes have been allocated (in Linux this can be done with malloc_usable_size, in Windows with _msize). This is not what you want because this does not tell you the size of an array but the amount of memory allocated. Since malloc is not necessarily giving you exactly as much memory as you have asked for, you cannot compute the array size from the result of malloc_usable_size:



#include <iostream>
#include <malloc.h>

int main()
{
std::cout << malloc_usable_size(malloc(42)) << std::endl;
}


This example gives you 56, not 42: http://cpp.sh/2wdm4



Note that applying malloc_usable_size (or _msize) to the result of new is undefined behavior.



So, let's now discuss construction and destruction of objects. Here, you have two ways of delete: delete (for single objects) and delete (for arrays). In very old versions of C++, you had to pass the size of the array to the delete-operator. As you mentioned, nowadays, this is not the case. The compiler tracks this information. GCC adds a small field prior the beginning of the array, where the size of the array is stored such that it knows how often the destructor has to be called. You might query that:



#include <iostream>

struct foo {
char a;
~foo() {}
};

int main()
{
foo * ptr = new foo[42];
std::cout << *(((std::size_t*)ptr)-1) << std::endl;
}


This code gives you 42: http://cpp.sh/7mbqq



Just for the protocol: This is undefined behavior, but with the current version of GCC it works.



So, you might ask yourself why there is no function to query this information. The answer is that GCC doesn't always store this information. There might be cases where destruction of the objects is a no-operation (and the compiler is able to figure that out). Consider the following example:



#include <iostream>

struct foo {
char a;
//~foo() {}
};

int main()
{
foo * ptr = new foo[42];
std::cout << *(((std::size_t*)ptr)-1) << std::endl;
}


Here, the answer is not 42 any more: http://cpp.sh/2rzfb



The answer is just garbage - the code was undefined behavior again.



Why? Because the compiler does not need to call a destructor, so it does not need to store the information. And, yes, in this case the compiler does not add code that keeps track how many objects have been created. Only the number of allocated bytes (which might be 56, see above) is known.






share|improve this answer





















  • 1





    Very interesting answer! I do wonder now what malloc_usable_size would give you for that second pointer though? And if it's the correct answer, where this information would have been stored?

    – Max Langhof
    yesterday






  • 1





    You can try this out but this is undefined behavior. For gcc, where new is based on malloc, it could work. However, if you consider an array of a not-trivally-destructible type (first example), ptr does for sure not point to the beginning of the memory that has been allocated by malloc (because of the hidden field in the beginning). Thus, I expect that malloc_usable_size does not work.

    – Handy999
    yesterday








  • 3





    Wonderful answer! So, the gist is: * The information N ("number of elements") may not be stored (it is only in case of dynamic arrays of things with a destructor). For this reason we need to keep track of the length manually, if we want it. * What is instead always stored is S ("size of allocated memory"). (S can be queried but results are implementation-dependent). * delete only needs S in order to deallocate memory (treats everything like a blob). It needs N only to know how many times to call destructors. * If N is stored, where it is stored is implementation-dependent. Correct?

    – Michele Piccolini
    yesterday











  • @Michele Piccolini: yes, excatly.

    – Handy999
    yesterday






  • 1





    @Michele Piccolini: do you like it like this?

    – Handy999
    15 hours ago



















25














It does - the allocator, or some implementation detail behind it, knows exactly what the size of the block is.



But that information is not provided to you or to the "code layer" of your program.



Could the language have been designed to do this? Sure! It's probably a case of "don't pay for what you don't use" — it's your responsibility to remember this information. After all, you know how much memory you asked for! Often times people will not want the cost of a number being passed up the call stack when, most of the time, they won't need it to be.



There are some platform-specific "extensions" that may get you what you want, like malloc_usable_size on Linux and _msize on Windows, though these assume that your allocator used malloc and didn't do any other magic that may extend the size of the allocated block at the lowest level. I'd say you're still better off tracking this yourself if you really need it… or using a vector.






share|improve this answer





















  • 4





    @MaxLanghof "If I have to keep track of it, then I have to pay extra at some point" The key word is if.

    – Lightness Races in Orbit
    yesterday






  • 4





    @MaxLanghof Admittedly I would be vaguely interested in finding out whether there's some crucial reason that this wasn't made part of the stdlib's allocation interface(s), that go beyond "we cba and don't think you should need this"

    – Lightness Races in Orbit
    yesterday






  • 1





    @MichelePiccolini The first question in your comment is unrelated to the topic at hand - correctly deleteing a pointer to an array if you already know it is a pointer to an array and being able to infer whether a pointer points to an array or a single object are two different, unrelated things. In other words, if there was an operator to infer the size that delete uses it would most certainly have UB if used on non-array allocations, thus it wouldn't allow you to decide whether the pointer is to an array allocation or not.

    – Max Langhof
    yesterday








  • 2





    @MichelePiccolini You shouldn't really be using delete or delete at all, though; that's for the insides of containers and smart pointers, which do have all this information nicely tucked away.

    – Lightness Races in Orbit
    yesterday






  • 2





    It might not know exactly, it might only know the size of the block it chose, which might tell it the size rounded up to the next multiple of 16 bytes, for example. Depending on the allocator of course. xD, @Handy999 already posted this as an answer before I commented.

    – Peter Cordes
    yesterday





















5














I think the reason for this is a confluence of three factors.




  1. C++ has a "you only pay for what you use" culture

  2. C++ started its life as a pre-processor for C and hence had to be built on top of what C offered.

  3. C++ is one of the most widely ported languages around. Features that make life difficult for existing ports are unlikely to get added.


C allows the programmer to free memory blocks without specifying the size of the memory block to free, but does not provide the programmer with any standard way to access the size of the allocation. Furthermore the actual amount of memory allocated may well be larger than the amount the programmer asked for.



Following the principle of "you only pay for what you use", C++ implementations implement new differently for different types. Typically they only store the size if it is necessary to do so, usually because the type has a non-trivial destructor.



So while yes, enough information is stored to free the memory block, it would be very difficult to define a sane and portable API for accessing that information. Depending on the data type and platform, the actual requested size may be available (for types where the C++ implementation has to store it), only the actual allocated size may be available (for types where the C++ implementation does not have to store it on platforms where the underlying memory manager has an extension to get the allocated size), or the size may not be available at all (for types where the C++ implementation does not have to store it on platforms that don't provide access to the information from the underlying memory manager).






share|improve this answer

































    1














    This answer applies to Microsoft Visual Studio only.



    There is a function called _msize, which will return the malloced / calloced / realloced size of a pointer.



    It can be found in the malloc.h header, and the parameters are:



    size_t _msize(
    void *memblock
    );


    I am not sure if there is an equivalent in gcc. There probably should be.






    share|improve this answer



















    • 1





      Ahh there is malloc_usable_size() for linux.

      – Owl
      yesterday











    • Do you know if those are reliable or what could be some cases that might arise and might make the usage of these non reliable?

      – Michele Piccolini
      yesterday






    • 2





      Well one of the things I noticed when I tested it, I called a malloc on an array of chars 25 long, then called malloc_usable_size on the array. It reported 40 bytes used. This suggests to me that it's actually reporting the container size allocated that is large enough to contain the array.

      – Owl
      yesterday



















    -1














    If delete doesn't have to know the size of the array at the time it is called, your entire argument falls apart. And delete doesn't have to know the size of the array at the time it is called. It only needs to know the size to make the block available for use by others, and absolutely nothing requires it to make the block available for use by others at the time delete is called.



    For example, delete my dice a large block into some number of smaller blocks. Each of those blocks but one need only have a pointer to the control block that knows the size. If any block but the control block is passed to delete first, then delete has no idea how big the block that was just freed is and won't know until later.



    That it is not absolutely required that delete know the size of a block at every arbitrary point during its lifetime is sufficient to invalidate your argument.






    share|improve this answer






























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      27














      TL;DR The operator delete destructs the objects and deallocates the memory. The information N ("number of elements") is required for destructing. The information S ("size of allocated memory") is required for deallocating. S is always stored and can be queried by compiler extensions. N is only stored if destructing objects requires calling destructors. If N is stored, where it is stored is implementation-dependent.





      The operator delete has to do two things:



      a) destructing the objects (calling destructors, if necessary) and



      b) deallocating the memory.



      Let's first discuss (de)allocation, which
      is delegated to the C functions malloc and free by many compilers (like GCC). The function malloc takes the number of bytes to be allocated as a parameter and returns a pointer. The function free takes only a pointer; the number of bytes is not necessary. This means that the memory allocating functions have to keep track how many bytes have been allocated. There could be a function to query how many bytes have been allocated (in Linux this can be done with malloc_usable_size, in Windows with _msize). This is not what you want because this does not tell you the size of an array but the amount of memory allocated. Since malloc is not necessarily giving you exactly as much memory as you have asked for, you cannot compute the array size from the result of malloc_usable_size:



      #include <iostream>
      #include <malloc.h>

      int main()
      {
      std::cout << malloc_usable_size(malloc(42)) << std::endl;
      }


      This example gives you 56, not 42: http://cpp.sh/2wdm4



      Note that applying malloc_usable_size (or _msize) to the result of new is undefined behavior.



      So, let's now discuss construction and destruction of objects. Here, you have two ways of delete: delete (for single objects) and delete (for arrays). In very old versions of C++, you had to pass the size of the array to the delete-operator. As you mentioned, nowadays, this is not the case. The compiler tracks this information. GCC adds a small field prior the beginning of the array, where the size of the array is stored such that it knows how often the destructor has to be called. You might query that:



      #include <iostream>

      struct foo {
      char a;
      ~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      This code gives you 42: http://cpp.sh/7mbqq



      Just for the protocol: This is undefined behavior, but with the current version of GCC it works.



      So, you might ask yourself why there is no function to query this information. The answer is that GCC doesn't always store this information. There might be cases where destruction of the objects is a no-operation (and the compiler is able to figure that out). Consider the following example:



      #include <iostream>

      struct foo {
      char a;
      //~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      Here, the answer is not 42 any more: http://cpp.sh/2rzfb



      The answer is just garbage - the code was undefined behavior again.



      Why? Because the compiler does not need to call a destructor, so it does not need to store the information. And, yes, in this case the compiler does not add code that keeps track how many objects have been created. Only the number of allocated bytes (which might be 56, see above) is known.






      share|improve this answer





















      • 1





        Very interesting answer! I do wonder now what malloc_usable_size would give you for that second pointer though? And if it's the correct answer, where this information would have been stored?

        – Max Langhof
        yesterday






      • 1





        You can try this out but this is undefined behavior. For gcc, where new is based on malloc, it could work. However, if you consider an array of a not-trivally-destructible type (first example), ptr does for sure not point to the beginning of the memory that has been allocated by malloc (because of the hidden field in the beginning). Thus, I expect that malloc_usable_size does not work.

        – Handy999
        yesterday








      • 3





        Wonderful answer! So, the gist is: * The information N ("number of elements") may not be stored (it is only in case of dynamic arrays of things with a destructor). For this reason we need to keep track of the length manually, if we want it. * What is instead always stored is S ("size of allocated memory"). (S can be queried but results are implementation-dependent). * delete only needs S in order to deallocate memory (treats everything like a blob). It needs N only to know how many times to call destructors. * If N is stored, where it is stored is implementation-dependent. Correct?

        – Michele Piccolini
        yesterday











      • @Michele Piccolini: yes, excatly.

        – Handy999
        yesterday






      • 1





        @Michele Piccolini: do you like it like this?

        – Handy999
        15 hours ago
















      27














      TL;DR The operator delete destructs the objects and deallocates the memory. The information N ("number of elements") is required for destructing. The information S ("size of allocated memory") is required for deallocating. S is always stored and can be queried by compiler extensions. N is only stored if destructing objects requires calling destructors. If N is stored, where it is stored is implementation-dependent.





      The operator delete has to do two things:



      a) destructing the objects (calling destructors, if necessary) and



      b) deallocating the memory.



      Let's first discuss (de)allocation, which
      is delegated to the C functions malloc and free by many compilers (like GCC). The function malloc takes the number of bytes to be allocated as a parameter and returns a pointer. The function free takes only a pointer; the number of bytes is not necessary. This means that the memory allocating functions have to keep track how many bytes have been allocated. There could be a function to query how many bytes have been allocated (in Linux this can be done with malloc_usable_size, in Windows with _msize). This is not what you want because this does not tell you the size of an array but the amount of memory allocated. Since malloc is not necessarily giving you exactly as much memory as you have asked for, you cannot compute the array size from the result of malloc_usable_size:



      #include <iostream>
      #include <malloc.h>

      int main()
      {
      std::cout << malloc_usable_size(malloc(42)) << std::endl;
      }


      This example gives you 56, not 42: http://cpp.sh/2wdm4



      Note that applying malloc_usable_size (or _msize) to the result of new is undefined behavior.



      So, let's now discuss construction and destruction of objects. Here, you have two ways of delete: delete (for single objects) and delete (for arrays). In very old versions of C++, you had to pass the size of the array to the delete-operator. As you mentioned, nowadays, this is not the case. The compiler tracks this information. GCC adds a small field prior the beginning of the array, where the size of the array is stored such that it knows how often the destructor has to be called. You might query that:



      #include <iostream>

      struct foo {
      char a;
      ~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      This code gives you 42: http://cpp.sh/7mbqq



      Just for the protocol: This is undefined behavior, but with the current version of GCC it works.



      So, you might ask yourself why there is no function to query this information. The answer is that GCC doesn't always store this information. There might be cases where destruction of the objects is a no-operation (and the compiler is able to figure that out). Consider the following example:



      #include <iostream>

      struct foo {
      char a;
      //~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      Here, the answer is not 42 any more: http://cpp.sh/2rzfb



      The answer is just garbage - the code was undefined behavior again.



      Why? Because the compiler does not need to call a destructor, so it does not need to store the information. And, yes, in this case the compiler does not add code that keeps track how many objects have been created. Only the number of allocated bytes (which might be 56, see above) is known.






      share|improve this answer





















      • 1





        Very interesting answer! I do wonder now what malloc_usable_size would give you for that second pointer though? And if it's the correct answer, where this information would have been stored?

        – Max Langhof
        yesterday






      • 1





        You can try this out but this is undefined behavior. For gcc, where new is based on malloc, it could work. However, if you consider an array of a not-trivally-destructible type (first example), ptr does for sure not point to the beginning of the memory that has been allocated by malloc (because of the hidden field in the beginning). Thus, I expect that malloc_usable_size does not work.

        – Handy999
        yesterday








      • 3





        Wonderful answer! So, the gist is: * The information N ("number of elements") may not be stored (it is only in case of dynamic arrays of things with a destructor). For this reason we need to keep track of the length manually, if we want it. * What is instead always stored is S ("size of allocated memory"). (S can be queried but results are implementation-dependent). * delete only needs S in order to deallocate memory (treats everything like a blob). It needs N only to know how many times to call destructors. * If N is stored, where it is stored is implementation-dependent. Correct?

        – Michele Piccolini
        yesterday











      • @Michele Piccolini: yes, excatly.

        – Handy999
        yesterday






      • 1





        @Michele Piccolini: do you like it like this?

        – Handy999
        15 hours ago














      27












      27








      27







      TL;DR The operator delete destructs the objects and deallocates the memory. The information N ("number of elements") is required for destructing. The information S ("size of allocated memory") is required for deallocating. S is always stored and can be queried by compiler extensions. N is only stored if destructing objects requires calling destructors. If N is stored, where it is stored is implementation-dependent.





      The operator delete has to do two things:



      a) destructing the objects (calling destructors, if necessary) and



      b) deallocating the memory.



      Let's first discuss (de)allocation, which
      is delegated to the C functions malloc and free by many compilers (like GCC). The function malloc takes the number of bytes to be allocated as a parameter and returns a pointer. The function free takes only a pointer; the number of bytes is not necessary. This means that the memory allocating functions have to keep track how many bytes have been allocated. There could be a function to query how many bytes have been allocated (in Linux this can be done with malloc_usable_size, in Windows with _msize). This is not what you want because this does not tell you the size of an array but the amount of memory allocated. Since malloc is not necessarily giving you exactly as much memory as you have asked for, you cannot compute the array size from the result of malloc_usable_size:



      #include <iostream>
      #include <malloc.h>

      int main()
      {
      std::cout << malloc_usable_size(malloc(42)) << std::endl;
      }


      This example gives you 56, not 42: http://cpp.sh/2wdm4



      Note that applying malloc_usable_size (or _msize) to the result of new is undefined behavior.



      So, let's now discuss construction and destruction of objects. Here, you have two ways of delete: delete (for single objects) and delete (for arrays). In very old versions of C++, you had to pass the size of the array to the delete-operator. As you mentioned, nowadays, this is not the case. The compiler tracks this information. GCC adds a small field prior the beginning of the array, where the size of the array is stored such that it knows how often the destructor has to be called. You might query that:



      #include <iostream>

      struct foo {
      char a;
      ~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      This code gives you 42: http://cpp.sh/7mbqq



      Just for the protocol: This is undefined behavior, but with the current version of GCC it works.



      So, you might ask yourself why there is no function to query this information. The answer is that GCC doesn't always store this information. There might be cases where destruction of the objects is a no-operation (and the compiler is able to figure that out). Consider the following example:



      #include <iostream>

      struct foo {
      char a;
      //~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      Here, the answer is not 42 any more: http://cpp.sh/2rzfb



      The answer is just garbage - the code was undefined behavior again.



      Why? Because the compiler does not need to call a destructor, so it does not need to store the information. And, yes, in this case the compiler does not add code that keeps track how many objects have been created. Only the number of allocated bytes (which might be 56, see above) is known.






      share|improve this answer















      TL;DR The operator delete destructs the objects and deallocates the memory. The information N ("number of elements") is required for destructing. The information S ("size of allocated memory") is required for deallocating. S is always stored and can be queried by compiler extensions. N is only stored if destructing objects requires calling destructors. If N is stored, where it is stored is implementation-dependent.





      The operator delete has to do two things:



      a) destructing the objects (calling destructors, if necessary) and



      b) deallocating the memory.



      Let's first discuss (de)allocation, which
      is delegated to the C functions malloc and free by many compilers (like GCC). The function malloc takes the number of bytes to be allocated as a parameter and returns a pointer. The function free takes only a pointer; the number of bytes is not necessary. This means that the memory allocating functions have to keep track how many bytes have been allocated. There could be a function to query how many bytes have been allocated (in Linux this can be done with malloc_usable_size, in Windows with _msize). This is not what you want because this does not tell you the size of an array but the amount of memory allocated. Since malloc is not necessarily giving you exactly as much memory as you have asked for, you cannot compute the array size from the result of malloc_usable_size:



      #include <iostream>
      #include <malloc.h>

      int main()
      {
      std::cout << malloc_usable_size(malloc(42)) << std::endl;
      }


      This example gives you 56, not 42: http://cpp.sh/2wdm4



      Note that applying malloc_usable_size (or _msize) to the result of new is undefined behavior.



      So, let's now discuss construction and destruction of objects. Here, you have two ways of delete: delete (for single objects) and delete (for arrays). In very old versions of C++, you had to pass the size of the array to the delete-operator. As you mentioned, nowadays, this is not the case. The compiler tracks this information. GCC adds a small field prior the beginning of the array, where the size of the array is stored such that it knows how often the destructor has to be called. You might query that:



      #include <iostream>

      struct foo {
      char a;
      ~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      This code gives you 42: http://cpp.sh/7mbqq



      Just for the protocol: This is undefined behavior, but with the current version of GCC it works.



      So, you might ask yourself why there is no function to query this information. The answer is that GCC doesn't always store this information. There might be cases where destruction of the objects is a no-operation (and the compiler is able to figure that out). Consider the following example:



      #include <iostream>

      struct foo {
      char a;
      //~foo() {}
      };

      int main()
      {
      foo * ptr = new foo[42];
      std::cout << *(((std::size_t*)ptr)-1) << std::endl;
      }


      Here, the answer is not 42 any more: http://cpp.sh/2rzfb



      The answer is just garbage - the code was undefined behavior again.



      Why? Because the compiler does not need to call a destructor, so it does not need to store the information. And, yes, in this case the compiler does not add code that keeps track how many objects have been created. Only the number of allocated bytes (which might be 56, see above) is known.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited 16 hours ago

























      answered yesterday









      Handy999Handy999

      48817




      48817








      • 1





        Very interesting answer! I do wonder now what malloc_usable_size would give you for that second pointer though? And if it's the correct answer, where this information would have been stored?

        – Max Langhof
        yesterday






      • 1





        You can try this out but this is undefined behavior. For gcc, where new is based on malloc, it could work. However, if you consider an array of a not-trivally-destructible type (first example), ptr does for sure not point to the beginning of the memory that has been allocated by malloc (because of the hidden field in the beginning). Thus, I expect that malloc_usable_size does not work.

        – Handy999
        yesterday








      • 3





        Wonderful answer! So, the gist is: * The information N ("number of elements") may not be stored (it is only in case of dynamic arrays of things with a destructor). For this reason we need to keep track of the length manually, if we want it. * What is instead always stored is S ("size of allocated memory"). (S can be queried but results are implementation-dependent). * delete only needs S in order to deallocate memory (treats everything like a blob). It needs N only to know how many times to call destructors. * If N is stored, where it is stored is implementation-dependent. Correct?

        – Michele Piccolini
        yesterday











      • @Michele Piccolini: yes, excatly.

        – Handy999
        yesterday






      • 1





        @Michele Piccolini: do you like it like this?

        – Handy999
        15 hours ago














      • 1





        Very interesting answer! I do wonder now what malloc_usable_size would give you for that second pointer though? And if it's the correct answer, where this information would have been stored?

        – Max Langhof
        yesterday






      • 1





        You can try this out but this is undefined behavior. For gcc, where new is based on malloc, it could work. However, if you consider an array of a not-trivally-destructible type (first example), ptr does for sure not point to the beginning of the memory that has been allocated by malloc (because of the hidden field in the beginning). Thus, I expect that malloc_usable_size does not work.

        – Handy999
        yesterday








      • 3





        Wonderful answer! So, the gist is: * The information N ("number of elements") may not be stored (it is only in case of dynamic arrays of things with a destructor). For this reason we need to keep track of the length manually, if we want it. * What is instead always stored is S ("size of allocated memory"). (S can be queried but results are implementation-dependent). * delete only needs S in order to deallocate memory (treats everything like a blob). It needs N only to know how many times to call destructors. * If N is stored, where it is stored is implementation-dependent. Correct?

        – Michele Piccolini
        yesterday











      • @Michele Piccolini: yes, excatly.

        – Handy999
        yesterday






      • 1





        @Michele Piccolini: do you like it like this?

        – Handy999
        15 hours ago








      1




      1





      Very interesting answer! I do wonder now what malloc_usable_size would give you for that second pointer though? And if it's the correct answer, where this information would have been stored?

      – Max Langhof
      yesterday





      Very interesting answer! I do wonder now what malloc_usable_size would give you for that second pointer though? And if it's the correct answer, where this information would have been stored?

      – Max Langhof
      yesterday




      1




      1





      You can try this out but this is undefined behavior. For gcc, where new is based on malloc, it could work. However, if you consider an array of a not-trivally-destructible type (first example), ptr does for sure not point to the beginning of the memory that has been allocated by malloc (because of the hidden field in the beginning). Thus, I expect that malloc_usable_size does not work.

      – Handy999
      yesterday







      You can try this out but this is undefined behavior. For gcc, where new is based on malloc, it could work. However, if you consider an array of a not-trivally-destructible type (first example), ptr does for sure not point to the beginning of the memory that has been allocated by malloc (because of the hidden field in the beginning). Thus, I expect that malloc_usable_size does not work.

      – Handy999
      yesterday






      3




      3





      Wonderful answer! So, the gist is: * The information N ("number of elements") may not be stored (it is only in case of dynamic arrays of things with a destructor). For this reason we need to keep track of the length manually, if we want it. * What is instead always stored is S ("size of allocated memory"). (S can be queried but results are implementation-dependent). * delete only needs S in order to deallocate memory (treats everything like a blob). It needs N only to know how many times to call destructors. * If N is stored, where it is stored is implementation-dependent. Correct?

      – Michele Piccolini
      yesterday





      Wonderful answer! So, the gist is: * The information N ("number of elements") may not be stored (it is only in case of dynamic arrays of things with a destructor). For this reason we need to keep track of the length manually, if we want it. * What is instead always stored is S ("size of allocated memory"). (S can be queried but results are implementation-dependent). * delete only needs S in order to deallocate memory (treats everything like a blob). It needs N only to know how many times to call destructors. * If N is stored, where it is stored is implementation-dependent. Correct?

      – Michele Piccolini
      yesterday













      @Michele Piccolini: yes, excatly.

      – Handy999
      yesterday





      @Michele Piccolini: yes, excatly.

      – Handy999
      yesterday




      1




      1





      @Michele Piccolini: do you like it like this?

      – Handy999
      15 hours ago





      @Michele Piccolini: do you like it like this?

      – Handy999
      15 hours ago













      25














      It does - the allocator, or some implementation detail behind it, knows exactly what the size of the block is.



      But that information is not provided to you or to the "code layer" of your program.



      Could the language have been designed to do this? Sure! It's probably a case of "don't pay for what you don't use" — it's your responsibility to remember this information. After all, you know how much memory you asked for! Often times people will not want the cost of a number being passed up the call stack when, most of the time, they won't need it to be.



      There are some platform-specific "extensions" that may get you what you want, like malloc_usable_size on Linux and _msize on Windows, though these assume that your allocator used malloc and didn't do any other magic that may extend the size of the allocated block at the lowest level. I'd say you're still better off tracking this yourself if you really need it… or using a vector.






      share|improve this answer





















      • 4





        @MaxLanghof "If I have to keep track of it, then I have to pay extra at some point" The key word is if.

        – Lightness Races in Orbit
        yesterday






      • 4





        @MaxLanghof Admittedly I would be vaguely interested in finding out whether there's some crucial reason that this wasn't made part of the stdlib's allocation interface(s), that go beyond "we cba and don't think you should need this"

        – Lightness Races in Orbit
        yesterday






      • 1





        @MichelePiccolini The first question in your comment is unrelated to the topic at hand - correctly deleteing a pointer to an array if you already know it is a pointer to an array and being able to infer whether a pointer points to an array or a single object are two different, unrelated things. In other words, if there was an operator to infer the size that delete uses it would most certainly have UB if used on non-array allocations, thus it wouldn't allow you to decide whether the pointer is to an array allocation or not.

        – Max Langhof
        yesterday








      • 2





        @MichelePiccolini You shouldn't really be using delete or delete at all, though; that's for the insides of containers and smart pointers, which do have all this information nicely tucked away.

        – Lightness Races in Orbit
        yesterday






      • 2





        It might not know exactly, it might only know the size of the block it chose, which might tell it the size rounded up to the next multiple of 16 bytes, for example. Depending on the allocator of course. xD, @Handy999 already posted this as an answer before I commented.

        – Peter Cordes
        yesterday


















      25














      It does - the allocator, or some implementation detail behind it, knows exactly what the size of the block is.



      But that information is not provided to you or to the "code layer" of your program.



      Could the language have been designed to do this? Sure! It's probably a case of "don't pay for what you don't use" — it's your responsibility to remember this information. After all, you know how much memory you asked for! Often times people will not want the cost of a number being passed up the call stack when, most of the time, they won't need it to be.



      There are some platform-specific "extensions" that may get you what you want, like malloc_usable_size on Linux and _msize on Windows, though these assume that your allocator used malloc and didn't do any other magic that may extend the size of the allocated block at the lowest level. I'd say you're still better off tracking this yourself if you really need it… or using a vector.






      share|improve this answer





















      • 4





        @MaxLanghof "If I have to keep track of it, then I have to pay extra at some point" The key word is if.

        – Lightness Races in Orbit
        yesterday






      • 4





        @MaxLanghof Admittedly I would be vaguely interested in finding out whether there's some crucial reason that this wasn't made part of the stdlib's allocation interface(s), that go beyond "we cba and don't think you should need this"

        – Lightness Races in Orbit
        yesterday






      • 1





        @MichelePiccolini The first question in your comment is unrelated to the topic at hand - correctly deleteing a pointer to an array if you already know it is a pointer to an array and being able to infer whether a pointer points to an array or a single object are two different, unrelated things. In other words, if there was an operator to infer the size that delete uses it would most certainly have UB if used on non-array allocations, thus it wouldn't allow you to decide whether the pointer is to an array allocation or not.

        – Max Langhof
        yesterday








      • 2





        @MichelePiccolini You shouldn't really be using delete or delete at all, though; that's for the insides of containers and smart pointers, which do have all this information nicely tucked away.

        – Lightness Races in Orbit
        yesterday






      • 2





        It might not know exactly, it might only know the size of the block it chose, which might tell it the size rounded up to the next multiple of 16 bytes, for example. Depending on the allocator of course. xD, @Handy999 already posted this as an answer before I commented.

        – Peter Cordes
        yesterday
















      25












      25








      25







      It does - the allocator, or some implementation detail behind it, knows exactly what the size of the block is.



      But that information is not provided to you or to the "code layer" of your program.



      Could the language have been designed to do this? Sure! It's probably a case of "don't pay for what you don't use" — it's your responsibility to remember this information. After all, you know how much memory you asked for! Often times people will not want the cost of a number being passed up the call stack when, most of the time, they won't need it to be.



      There are some platform-specific "extensions" that may get you what you want, like malloc_usable_size on Linux and _msize on Windows, though these assume that your allocator used malloc and didn't do any other magic that may extend the size of the allocated block at the lowest level. I'd say you're still better off tracking this yourself if you really need it… or using a vector.






      share|improve this answer















      It does - the allocator, or some implementation detail behind it, knows exactly what the size of the block is.



      But that information is not provided to you or to the "code layer" of your program.



      Could the language have been designed to do this? Sure! It's probably a case of "don't pay for what you don't use" — it's your responsibility to remember this information. After all, you know how much memory you asked for! Often times people will not want the cost of a number being passed up the call stack when, most of the time, they won't need it to be.



      There are some platform-specific "extensions" that may get you what you want, like malloc_usable_size on Linux and _msize on Windows, though these assume that your allocator used malloc and didn't do any other magic that may extend the size of the allocated block at the lowest level. I'd say you're still better off tracking this yourself if you really need it… or using a vector.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited yesterday

























      answered yesterday









      Lightness Races in OrbitLightness Races in Orbit

      291k52474807




      291k52474807








      • 4





        @MaxLanghof "If I have to keep track of it, then I have to pay extra at some point" The key word is if.

        – Lightness Races in Orbit
        yesterday






      • 4





        @MaxLanghof Admittedly I would be vaguely interested in finding out whether there's some crucial reason that this wasn't made part of the stdlib's allocation interface(s), that go beyond "we cba and don't think you should need this"

        – Lightness Races in Orbit
        yesterday






      • 1





        @MichelePiccolini The first question in your comment is unrelated to the topic at hand - correctly deleteing a pointer to an array if you already know it is a pointer to an array and being able to infer whether a pointer points to an array or a single object are two different, unrelated things. In other words, if there was an operator to infer the size that delete uses it would most certainly have UB if used on non-array allocations, thus it wouldn't allow you to decide whether the pointer is to an array allocation or not.

        – Max Langhof
        yesterday








      • 2





        @MichelePiccolini You shouldn't really be using delete or delete at all, though; that's for the insides of containers and smart pointers, which do have all this information nicely tucked away.

        – Lightness Races in Orbit
        yesterday






      • 2





        It might not know exactly, it might only know the size of the block it chose, which might tell it the size rounded up to the next multiple of 16 bytes, for example. Depending on the allocator of course. xD, @Handy999 already posted this as an answer before I commented.

        – Peter Cordes
        yesterday
















      • 4





        @MaxLanghof "If I have to keep track of it, then I have to pay extra at some point" The key word is if.

        – Lightness Races in Orbit
        yesterday






      • 4





        @MaxLanghof Admittedly I would be vaguely interested in finding out whether there's some crucial reason that this wasn't made part of the stdlib's allocation interface(s), that go beyond "we cba and don't think you should need this"

        – Lightness Races in Orbit
        yesterday






      • 1





        @MichelePiccolini The first question in your comment is unrelated to the topic at hand - correctly deleteing a pointer to an array if you already know it is a pointer to an array and being able to infer whether a pointer points to an array or a single object are two different, unrelated things. In other words, if there was an operator to infer the size that delete uses it would most certainly have UB if used on non-array allocations, thus it wouldn't allow you to decide whether the pointer is to an array allocation or not.

        – Max Langhof
        yesterday








      • 2





        @MichelePiccolini You shouldn't really be using delete or delete at all, though; that's for the insides of containers and smart pointers, which do have all this information nicely tucked away.

        – Lightness Races in Orbit
        yesterday






      • 2





        It might not know exactly, it might only know the size of the block it chose, which might tell it the size rounded up to the next multiple of 16 bytes, for example. Depending on the allocator of course. xD, @Handy999 already posted this as an answer before I commented.

        – Peter Cordes
        yesterday










      4




      4





      @MaxLanghof "If I have to keep track of it, then I have to pay extra at some point" The key word is if.

      – Lightness Races in Orbit
      yesterday





      @MaxLanghof "If I have to keep track of it, then I have to pay extra at some point" The key word is if.

      – Lightness Races in Orbit
      yesterday




      4




      4





      @MaxLanghof Admittedly I would be vaguely interested in finding out whether there's some crucial reason that this wasn't made part of the stdlib's allocation interface(s), that go beyond "we cba and don't think you should need this"

      – Lightness Races in Orbit
      yesterday





      @MaxLanghof Admittedly I would be vaguely interested in finding out whether there's some crucial reason that this wasn't made part of the stdlib's allocation interface(s), that go beyond "we cba and don't think you should need this"

      – Lightness Races in Orbit
      yesterday




      1




      1





      @MichelePiccolini The first question in your comment is unrelated to the topic at hand - correctly deleteing a pointer to an array if you already know it is a pointer to an array and being able to infer whether a pointer points to an array or a single object are two different, unrelated things. In other words, if there was an operator to infer the size that delete uses it would most certainly have UB if used on non-array allocations, thus it wouldn't allow you to decide whether the pointer is to an array allocation or not.

      – Max Langhof
      yesterday







      @MichelePiccolini The first question in your comment is unrelated to the topic at hand - correctly deleteing a pointer to an array if you already know it is a pointer to an array and being able to infer whether a pointer points to an array or a single object are two different, unrelated things. In other words, if there was an operator to infer the size that delete uses it would most certainly have UB if used on non-array allocations, thus it wouldn't allow you to decide whether the pointer is to an array allocation or not.

      – Max Langhof
      yesterday






      2




      2





      @MichelePiccolini You shouldn't really be using delete or delete at all, though; that's for the insides of containers and smart pointers, which do have all this information nicely tucked away.

      – Lightness Races in Orbit
      yesterday





      @MichelePiccolini You shouldn't really be using delete or delete at all, though; that's for the insides of containers and smart pointers, which do have all this information nicely tucked away.

      – Lightness Races in Orbit
      yesterday




      2




      2





      It might not know exactly, it might only know the size of the block it chose, which might tell it the size rounded up to the next multiple of 16 bytes, for example. Depending on the allocator of course. xD, @Handy999 already posted this as an answer before I commented.

      – Peter Cordes
      yesterday







      It might not know exactly, it might only know the size of the block it chose, which might tell it the size rounded up to the next multiple of 16 bytes, for example. Depending on the allocator of course. xD, @Handy999 already posted this as an answer before I commented.

      – Peter Cordes
      yesterday













      5














      I think the reason for this is a confluence of three factors.




      1. C++ has a "you only pay for what you use" culture

      2. C++ started its life as a pre-processor for C and hence had to be built on top of what C offered.

      3. C++ is one of the most widely ported languages around. Features that make life difficult for existing ports are unlikely to get added.


      C allows the programmer to free memory blocks without specifying the size of the memory block to free, but does not provide the programmer with any standard way to access the size of the allocation. Furthermore the actual amount of memory allocated may well be larger than the amount the programmer asked for.



      Following the principle of "you only pay for what you use", C++ implementations implement new differently for different types. Typically they only store the size if it is necessary to do so, usually because the type has a non-trivial destructor.



      So while yes, enough information is stored to free the memory block, it would be very difficult to define a sane and portable API for accessing that information. Depending on the data type and platform, the actual requested size may be available (for types where the C++ implementation has to store it), only the actual allocated size may be available (for types where the C++ implementation does not have to store it on platforms where the underlying memory manager has an extension to get the allocated size), or the size may not be available at all (for types where the C++ implementation does not have to store it on platforms that don't provide access to the information from the underlying memory manager).






      share|improve this answer






























        5














        I think the reason for this is a confluence of three factors.




        1. C++ has a "you only pay for what you use" culture

        2. C++ started its life as a pre-processor for C and hence had to be built on top of what C offered.

        3. C++ is one of the most widely ported languages around. Features that make life difficult for existing ports are unlikely to get added.


        C allows the programmer to free memory blocks without specifying the size of the memory block to free, but does not provide the programmer with any standard way to access the size of the allocation. Furthermore the actual amount of memory allocated may well be larger than the amount the programmer asked for.



        Following the principle of "you only pay for what you use", C++ implementations implement new differently for different types. Typically they only store the size if it is necessary to do so, usually because the type has a non-trivial destructor.



        So while yes, enough information is stored to free the memory block, it would be very difficult to define a sane and portable API for accessing that information. Depending on the data type and platform, the actual requested size may be available (for types where the C++ implementation has to store it), only the actual allocated size may be available (for types where the C++ implementation does not have to store it on platforms where the underlying memory manager has an extension to get the allocated size), or the size may not be available at all (for types where the C++ implementation does not have to store it on platforms that don't provide access to the information from the underlying memory manager).






        share|improve this answer




























          5












          5








          5







          I think the reason for this is a confluence of three factors.




          1. C++ has a "you only pay for what you use" culture

          2. C++ started its life as a pre-processor for C and hence had to be built on top of what C offered.

          3. C++ is one of the most widely ported languages around. Features that make life difficult for existing ports are unlikely to get added.


          C allows the programmer to free memory blocks without specifying the size of the memory block to free, but does not provide the programmer with any standard way to access the size of the allocation. Furthermore the actual amount of memory allocated may well be larger than the amount the programmer asked for.



          Following the principle of "you only pay for what you use", C++ implementations implement new differently for different types. Typically they only store the size if it is necessary to do so, usually because the type has a non-trivial destructor.



          So while yes, enough information is stored to free the memory block, it would be very difficult to define a sane and portable API for accessing that information. Depending on the data type and platform, the actual requested size may be available (for types where the C++ implementation has to store it), only the actual allocated size may be available (for types where the C++ implementation does not have to store it on platforms where the underlying memory manager has an extension to get the allocated size), or the size may not be available at all (for types where the C++ implementation does not have to store it on platforms that don't provide access to the information from the underlying memory manager).






          share|improve this answer















          I think the reason for this is a confluence of three factors.




          1. C++ has a "you only pay for what you use" culture

          2. C++ started its life as a pre-processor for C and hence had to be built on top of what C offered.

          3. C++ is one of the most widely ported languages around. Features that make life difficult for existing ports are unlikely to get added.


          C allows the programmer to free memory blocks without specifying the size of the memory block to free, but does not provide the programmer with any standard way to access the size of the allocation. Furthermore the actual amount of memory allocated may well be larger than the amount the programmer asked for.



          Following the principle of "you only pay for what you use", C++ implementations implement new differently for different types. Typically they only store the size if it is necessary to do so, usually because the type has a non-trivial destructor.



          So while yes, enough information is stored to free the memory block, it would be very difficult to define a sane and portable API for accessing that information. Depending on the data type and platform, the actual requested size may be available (for types where the C++ implementation has to store it), only the actual allocated size may be available (for types where the C++ implementation does not have to store it on platforms where the underlying memory manager has an extension to get the allocated size), or the size may not be available at all (for types where the C++ implementation does not have to store it on platforms that don't provide access to the information from the underlying memory manager).







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited yesterday









          Toby Speight

          16.8k134265




          16.8k134265










          answered yesterday









          plugwashplugwash

          4,5071126




          4,5071126























              1














              This answer applies to Microsoft Visual Studio only.



              There is a function called _msize, which will return the malloced / calloced / realloced size of a pointer.



              It can be found in the malloc.h header, and the parameters are:



              size_t _msize(
              void *memblock
              );


              I am not sure if there is an equivalent in gcc. There probably should be.






              share|improve this answer



















              • 1





                Ahh there is malloc_usable_size() for linux.

                – Owl
                yesterday











              • Do you know if those are reliable or what could be some cases that might arise and might make the usage of these non reliable?

                – Michele Piccolini
                yesterday






              • 2





                Well one of the things I noticed when I tested it, I called a malloc on an array of chars 25 long, then called malloc_usable_size on the array. It reported 40 bytes used. This suggests to me that it's actually reporting the container size allocated that is large enough to contain the array.

                – Owl
                yesterday
















              1














              This answer applies to Microsoft Visual Studio only.



              There is a function called _msize, which will return the malloced / calloced / realloced size of a pointer.



              It can be found in the malloc.h header, and the parameters are:



              size_t _msize(
              void *memblock
              );


              I am not sure if there is an equivalent in gcc. There probably should be.






              share|improve this answer



















              • 1





                Ahh there is malloc_usable_size() for linux.

                – Owl
                yesterday











              • Do you know if those are reliable or what could be some cases that might arise and might make the usage of these non reliable?

                – Michele Piccolini
                yesterday






              • 2





                Well one of the things I noticed when I tested it, I called a malloc on an array of chars 25 long, then called malloc_usable_size on the array. It reported 40 bytes used. This suggests to me that it's actually reporting the container size allocated that is large enough to contain the array.

                – Owl
                yesterday














              1












              1








              1







              This answer applies to Microsoft Visual Studio only.



              There is a function called _msize, which will return the malloced / calloced / realloced size of a pointer.



              It can be found in the malloc.h header, and the parameters are:



              size_t _msize(
              void *memblock
              );


              I am not sure if there is an equivalent in gcc. There probably should be.






              share|improve this answer













              This answer applies to Microsoft Visual Studio only.



              There is a function called _msize, which will return the malloced / calloced / realloced size of a pointer.



              It can be found in the malloc.h header, and the parameters are:



              size_t _msize(
              void *memblock
              );


              I am not sure if there is an equivalent in gcc. There probably should be.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered yesterday









              OwlOwl

              656511




              656511








              • 1





                Ahh there is malloc_usable_size() for linux.

                – Owl
                yesterday











              • Do you know if those are reliable or what could be some cases that might arise and might make the usage of these non reliable?

                – Michele Piccolini
                yesterday






              • 2





                Well one of the things I noticed when I tested it, I called a malloc on an array of chars 25 long, then called malloc_usable_size on the array. It reported 40 bytes used. This suggests to me that it's actually reporting the container size allocated that is large enough to contain the array.

                – Owl
                yesterday














              • 1





                Ahh there is malloc_usable_size() for linux.

                – Owl
                yesterday











              • Do you know if those are reliable or what could be some cases that might arise and might make the usage of these non reliable?

                – Michele Piccolini
                yesterday






              • 2





                Well one of the things I noticed when I tested it, I called a malloc on an array of chars 25 long, then called malloc_usable_size on the array. It reported 40 bytes used. This suggests to me that it's actually reporting the container size allocated that is large enough to contain the array.

                – Owl
                yesterday








              1




              1





              Ahh there is malloc_usable_size() for linux.

              – Owl
              yesterday





              Ahh there is malloc_usable_size() for linux.

              – Owl
              yesterday













              Do you know if those are reliable or what could be some cases that might arise and might make the usage of these non reliable?

              – Michele Piccolini
              yesterday





              Do you know if those are reliable or what could be some cases that might arise and might make the usage of these non reliable?

              – Michele Piccolini
              yesterday




              2




              2





              Well one of the things I noticed when I tested it, I called a malloc on an array of chars 25 long, then called malloc_usable_size on the array. It reported 40 bytes used. This suggests to me that it's actually reporting the container size allocated that is large enough to contain the array.

              – Owl
              yesterday





              Well one of the things I noticed when I tested it, I called a malloc on an array of chars 25 long, then called malloc_usable_size on the array. It reported 40 bytes used. This suggests to me that it's actually reporting the container size allocated that is large enough to contain the array.

              – Owl
              yesterday











              -1














              If delete doesn't have to know the size of the array at the time it is called, your entire argument falls apart. And delete doesn't have to know the size of the array at the time it is called. It only needs to know the size to make the block available for use by others, and absolutely nothing requires it to make the block available for use by others at the time delete is called.



              For example, delete my dice a large block into some number of smaller blocks. Each of those blocks but one need only have a pointer to the control block that knows the size. If any block but the control block is passed to delete first, then delete has no idea how big the block that was just freed is and won't know until later.



              That it is not absolutely required that delete know the size of a block at every arbitrary point during its lifetime is sufficient to invalidate your argument.






              share|improve this answer




























                -1














                If delete doesn't have to know the size of the array at the time it is called, your entire argument falls apart. And delete doesn't have to know the size of the array at the time it is called. It only needs to know the size to make the block available for use by others, and absolutely nothing requires it to make the block available for use by others at the time delete is called.



                For example, delete my dice a large block into some number of smaller blocks. Each of those blocks but one need only have a pointer to the control block that knows the size. If any block but the control block is passed to delete first, then delete has no idea how big the block that was just freed is and won't know until later.



                That it is not absolutely required that delete know the size of a block at every arbitrary point during its lifetime is sufficient to invalidate your argument.






                share|improve this answer


























                  -1












                  -1








                  -1







                  If delete doesn't have to know the size of the array at the time it is called, your entire argument falls apart. And delete doesn't have to know the size of the array at the time it is called. It only needs to know the size to make the block available for use by others, and absolutely nothing requires it to make the block available for use by others at the time delete is called.



                  For example, delete my dice a large block into some number of smaller blocks. Each of those blocks but one need only have a pointer to the control block that knows the size. If any block but the control block is passed to delete first, then delete has no idea how big the block that was just freed is and won't know until later.



                  That it is not absolutely required that delete know the size of a block at every arbitrary point during its lifetime is sufficient to invalidate your argument.






                  share|improve this answer













                  If delete doesn't have to know the size of the array at the time it is called, your entire argument falls apart. And delete doesn't have to know the size of the array at the time it is called. It only needs to know the size to make the block available for use by others, and absolutely nothing requires it to make the block available for use by others at the time delete is called.



                  For example, delete my dice a large block into some number of smaller blocks. Each of those blocks but one need only have a pointer to the control block that knows the size. If any block but the control block is passed to delete first, then delete has no idea how big the block that was just freed is and won't know until later.



                  That it is not absolutely required that delete know the size of a block at every arbitrary point during its lifetime is sufficient to invalidate your argument.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 21 hours ago









                  David SchwartzDavid Schwartz

                  137k14144226




                  137k14144226















                      Popular posts from this blog

                      How to label and detect the document text images

                      Vallis Paradisi

                      Tabula Rosettana