| 290 | } |
| 291 | |
| 292 | extern "C" void* mc_realloc(void* ptr, size_t size) |
| 293 | { |
| 294 | // special case size == 0 -> free() |
| 295 | if(size == 0) { |
| 296 | mc_free(ptr); |
| 297 | return nullptr; |
| 298 | } |
| 299 | |
| 300 | // special case ptr == 0 -> malloc() |
| 301 | if(ptr == nullptr) { |
| 302 | return mc_malloc(size); |
| 303 | } |
| 304 | |
| 305 | if(*getSentinel(ptr) != sentinel) { |
| 306 | log("free(%p) has no sentinel !!! memory corruption?", ptr); |
| 307 | // ... or memory not allocated by our malloc() |
| 308 | return REAL(F_REALLOC)(ptr, size); |
| 309 | } |
| 310 | |
| 311 | // For testing purposes we'll assume the reallocation won't be in-place |
| 312 | if(allocationLimit != 0 && stats.current + size > allocationLimit) { |
| 313 | log("remalloc(%u) -> exceeds maximum (current is %u bytes)", size, stats.current); |
| 314 | return nullptr; |
| 315 | } |
| 316 | |
| 317 | ptr = offsetPointer(ptr, -alignment); |
| 318 | |
| 319 | size_t oldsize = *static_cast<size_t*>(ptr); |
| 320 | |
| 321 | void* newptr = REAL(F_REALLOC)(ptr, alignment + size); |
| 322 | |
| 323 | if(newptr == nullptr) { |
| 324 | log("realloc(%u -> %u) failed", oldsize, size); |
| 325 | return nullptr; |
| 326 | } |
| 327 | |
| 328 | dec_count(oldsize); |
| 329 | inc_count(size); |
| 330 | |
| 331 | if(size >= logThreshold) { |
| 332 | if(newptr == ptr) { |
| 333 | log("realloc(%u -> %u) = %p (cur %u)", oldsize, size, offsetPointer(newptr, alignment), stats.current); |
| 334 | } else { |
| 335 | log("realloc(%u -> %u) = %p -> %p (cur %u)", oldsize, size, offsetPointer(ptr, alignment), |
| 336 | offsetPointer(newptr, alignment), stats.current); |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | *static_cast<size_t*>(newptr) = size; |
| 341 | |
| 342 | return offsetPointer(newptr, alignment); |
| 343 | } |
| 344 | |
| 345 | static __attribute__((destructor)) void finish() |
| 346 | { |
nothing calls this directly
no test coverage detected