I've allocated an "array" of mystruct
of size n
like this:
if (NULL == (p = calloc(sizeof(struct mystruct) * n,1))) {
/* handle error */
}
Later on, I only have access to p
, and no longer have n
. Is there a way to determine the length of the array given just the pointer p
?
I figure it must be possible, since free(p)
does just that. I know malloc()
keeps track of how much memory it has allocated, and that's why it knows the length; perhaps there is a way to query for this information? Something like...
int length = askMallocLibraryHowMuchMemoryWasAlloced(p) / sizeof(mystruct)
I know I should just rework the code so that I know n
, but I'd rather not if possible. Any ideas?
really your question is - "can I find out the size of a malloc'd (or calloc'd) data block". And as others have said: no, not in a standard way.
However there are custom malloc implementations that do it - for example http://dmalloc.com/
Other have discussed the limits of plain c pointers and the
stdlib.h
implementations ofmalloc()
. Some implementations provide extensions which return the allocated block size which may be larger than the requested size.If you must have this behavior you can use or write a specialized memory allocator. This simplest thing to do would be implementing a wrapper around the
stdlib.h
functions. Some thing like:malloc will return a block of memory at least as big as you requested, but possibly bigger. So even if you could query the block size, this would not reliably give you your array size. So you'll just have to modify your code to keep track of it yourself.
Just to confirm the previous answers: There is no way to know, just by studying a pointer, how much memory was allocated by a malloc which returned this pointer.
What if it worked?
One example of why this is not possible. Let's imagine the code with an hypothetic function called get_size(void *) which returns the memory allocated for a pointer:
Why even if it worked, it would not work anyway?
But the problem of this approach is that, in C, you can play with pointer arithmetics. Let's rewrite doSomethingElse():
How get_size is supposed to work, as you sent the function a valid pointer, but not the one returned by malloc. And even if get_size went through all the trouble to find the size (i.e. in an inefficient way), it would return, in this case, a value that would be wrong in your context.
Conclusion
There are always ways to avoid this problem, and in C, you can always write your own allocator, but again, it is perhaps too much trouble when all you need is to remember how much memory was allocated.
May I recommend a terrible way to do it?
Allocate all your arrays as follows:
Then you can always cast your arrays to
int *
and access the -1st element.Be sure to
free
that pointer, and not the array pointer itself!Also, this will likely cause terrible bugs that will leave you tearing your hair out. Maybe you can wrap the alloc funcs in API calls or something.
No, there is no way to get this information without depending strongly on the implementation details of
malloc
. In particular,malloc
may allocate more bytes than you request (e.g. for efficiency in a particular memory architecture). It would be much better to redesign your code so that you keep track ofn
explicitly. The alternative is at least as much redesign and a much more dangerous approach (given that it's non-standard, abuses the semantics of pointers, and will be a maintenance nightmare for those that come after you): store the lengthn
at the malloc'd address, followed by the array. Allocation would then be:n
is now stored at*((unsigned long int*)p)
and the start of your array is nowEdit: Just to play devil's advocate... I know that these "solutions" all require redesigns, but let's play it out. Of course, the solution presented above is just a hacky implementation of a (well-packed) struct. You might as well define:
and pass around
arrInfo
s rather than raw pointers.Now we're cooking. But as long as you're redesigning, why stop here? What you really want is an abstract data type (ADT). Any introductory text for an algorithms and data structures class would do it. An ADT defines the public interface of a data type but hides the implementation of that data type. Thus, publicly an ADT for an array might look like
In other words, an ADT is a form of data and behavior encapsulation... in other words, it's about as close as you can get to Object-Oriented Programming using straight C. Unless you're stuck on a platform that doesn't have a C++ compiler, you might as well go whole hog and just use an STL
std::vector
.There, we've taken a simple question about C and ended up at C++. God help us all.