First, what is “memory fragmentation”, it is when your heap gets a lot of smallish memory blocks in it that can’t be used to make larger memory requests, even if you have enough “free” memory, it just isn’t contigous. This happens if the program allocates memory buffers of varing size, especially if it is of varying duration. How sever this problem is depends on how tight you are trying to size your heaps (fragmentation means you need to have more heap than your total memory requrements, as the fragmented blocks are not fully usable), and the ability of your system to tolerate an out of memory situation.
Now, if we look at malloc(), the first big issue is that out of the box, most mallocs are not "thread safe, unless specifically designed for the OS they are running under (this is what pvPortMalloc does), but my be defined with a stub callback that allows it to be made thread safe for the system. Unless your implementation provides such a set of stubs for FreeRTOS, you will need to find out if the library can, and how, to make it have that safety. I am not familiar with the ESP32 ecosystem to know what has been provided.
On the other hand, having your code use pvPortMalloc doesn’t mean the rest of the run-time librarty will use it, so you may need to be careful with what parts of the library you use.
A second issue with pvPortMalloc is that it isn’t just one implementation, but you will need to choose which one of them you will use (or you can provide your own).
heap1.c would likely not be usable, as it is a minimal verison that doesn’t support free().
heap2.c is also likely not usable, as while it minimally supports free(), it doesn’t keep enough information to merge free’ed blocks, so it more prone to fragmentation in programs that use a lot of dynamic memory.
The biggest issue with using both is that now you need to divide your heap definitons to allocate the needed memory for both, and you still have the issue that malloc might not be safe, unless you can make sure that all uses of malloc occur before the scheduler starts. If you can do this, then heap3 has the advantable that it just wraps malloc(), and thus makes it thread safe. On the other hand, if you can make malloc() thread safe, you don’t even need the wrapper (unless you still want the out of memory trap that pvPortMalloc can provide).