There are some counterpoints:
1) Conceptually, allocated memory block and data structure / array in it are not related. You can allocate memory block and then subdivide it to multiple different structures / arrays. You can implement sub-allocators.
2) Heap allocator does not need to store exact length of allocated object. For example, it could have several fixed-length slab allocators for smaller objects, select matching one during malloc() and use address range to find slab during free().
3) Array can be also on the stack (VLA or alloca()).
4) Arrays can be also on memory allocated outside of C library allocator (e.g. mmap()).