microsoft / mimalloc

mimalloc is a compact general purpose allocator with excellent performance.
MIT License
9.74k stars 793 forks source link

2.1.2 Windows 11: abort() called from _mi_segment_of() on "foreign" pointer #855

Closed rwiesenfarth closed 4 months ago

rwiesenfarth commented 4 months ago

I have some applications built by myself which call abort() on exit. I could trace this down to _mi_segment_of(). Here an example call stack:

_mi_assert_fail(const char * assertion, const char * fname, unsigned int line, const char * func) at options.c(380)
_mi_segment_of(const void * p) at segment-map.c(76)
mi_is_valid_pointer(const void *) at segment-map.c(128)
mi_is_in_heap_region(const void * p) at segment-map.c(132)
[External Code]

The code is this:

// Determine the segment belonging to a pointer or NULL if it is not in a valid segment.
static mi_segment_t* _mi_segment_of(const void* p) {
  if (p == NULL) return NULL;
  mi_segment_t* segment = _mi_ptr_segment(p);
  mi_assert_internal(segment != NULL); // <=== This line causing the abort() call
  size_t bitidx;
  size_t index = mi_segment_map_index_of(segment, &bitidx);

The pointer in question (p) is 0x00000000005bf070, so it was probably not allocated using mimalloc. Nevertheless, I would expect _mi_segment_of() returns NULL (as the comment says) if p is not a valid pointer.

The workaround for Release builds is to define NDEBUG (as suggested in types.h(40)), but this will not work for Debug builds (which define _DEBUG).

Is this behavior intended? Or could

mi_assert_internal(segment != NULL);

be replaced by

if(segment == NULL)
  return NULL;
daanx commented 4 months ago

Thanks for report -- I pushed a possible fix (in dev for now); can you test it?

rwiesenfarth commented 4 months ago

Did not test it explicitely, but as setting MI_DEBUG to 1 (which makes mi_assert_internal() a no-op) solves the issue, your change will do the same.