I agree. A lot of blocks which get allocated are never resized (e.g. objects), while other blocks may be subjected to frequent resizing - expanding buffers and strings being the most common example. malloc()/realloc() are very simple APIs, and work for the general purpose of "I want to allocate some memory/resize it", but this simplicity also means that they can't take advantage of specific usage patterns very well.
Working with data of indeterminate size is always going to involve more complexity, and while it may look like a solved problem (just resize when there is not enough space left) as evidenced by the proliferation of string implementations in various languages, the efficiency aspects are more subtle and still well within the area of "programmer must know what he/she is doing". Designing systems and protocols that don't need resizing of allocations, for example (how long something is, is easily calculated and known in advance.)