Help resolving crash after using malloc_get_all_zones()

In an ObjC framework I'm developing (a dylib) that is loaded into JRE to be used via JNI (Zulu, Graal, or "native image" from Graal+ a JAR) I implemented a naive method that collects current memory footprint of the host process: It collects 5 numbers into a simple NSDictionary with NSString keys (physical footprint, default zone bytes used and allocated, and sums for used and allocated bytes for all zones.

The code ran for some time, but at certain point my process started crashing horribly in this method -- at the last line, accessing the dictionary.

Here's the code:

-(NSDictionary *)memoryState {
    NSMutableDictionary *memoryState = [NSMutableDictionary dictionaryWithCapacity:8];
    // obtain process current physical memory footprint, in bytes.
    task_vm_info_data_t info;
    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
    kern_return_t kr = task_info(mach_task_self(),
                                 TASK_VM_INFO, (task_info_t)&info, &count);
    
    [memoryState setObject:(kr == KERN_SUCCESS) ? @(info.phys_footprint) : [NSNull null] forKey:@"physical"];
    
    // obtain process default zone's allocated memory, in bytes.
    malloc_zone_t *zone = malloc_default_zone();
    if (zone!=nil) {
        malloc_statistics_t st;
        malloc_zone_statistics(zone, &st);
        [memoryState setObject:@(st.size_in_use) forKey:@"bytesInUseDefaultZone"];
        [memoryState setObject:@(st.size_allocated) forKey:@"bytesAllocatedDefaultZone"];
    }
    
    uint64_t zone_count = 0, size_in_use =0, size_allocated = 0;
    vm_address_t *zones = NULL;
    unsigned int zones_count = 0;
    kr = malloc_get_all_zones(mach_task_self(), NULL, &zones, &zones_count);
    if (kr == KERN_SUCCESS && zones != NULL && zones_count > 0) {
        for (unsigned int i = 0; i < zones_count; i++) {
            malloc_zone_t *zone = (malloc_zone_t *)zones[i];
            if (!zone) continue;
            malloc_statistics_t st;
            malloc_zone_statistics(zone, &st);
            zone_count++;
            size_in_use     += (uint64_t)st.size_in_use;
            size_allocated  += (uint64_t)st.size_allocated;
        }
        [memoryState setObject:@(size_in_use) forKey:@"bytesInUseAllZones"];
        [memoryState setObject:@(size_allocated) forKey:@"bytesAllocatedAllZones"];
    }

    if (zones != NULL) {
        vm_deallocate(mach_task_self(), (vm_address_t)zones, zones_count * sizeof(vm_address_t));
    }
    return [memoryState copy];
}

my (JRE) process started crashing badly, at the last [memoryState copy]; with crash report I could not understand (looks like an infinite recursion or loop).

Any debug log messages (os_log) for this memoryState, its items or its copy would crash the same.

Finally I found that commenting out the vm_deallocate() call removes the crash.

Sorry to say - I could NOT find anywhere in the documentation anything about malloc_get_all_zones() returned data, and whether I need to deallocate it after use. Some darn AI analyzer pointed out I "had a leak" and that "Apple documentation" which it didn't provide, requires that I thus release this data.

1 ) Do I really have to deallocate the returned "zones" ?? even if I do, something here is strange - zones is a malloc_zone_t ** -- how can it be casted to (vm_address_t)zones

  1. Where can I read actual documentation about these low level APIs and the correct use?

Thanks!

Help resolving crash after using malloc_get_all_zones()
 
 
Q