15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2012 Google Inc. All Rights Reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------------- 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Misc. common utility functions 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Skal (pascal.massimino@gmail.com) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./utils.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// If PRINT_MEM_INFO is defined, extra info (like total memory used, number of 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// alloc/free etc) is printed. For debugging/tuning purpose only (it's slow, 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// and not multi-thread safe!). 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// An interesting alternative is valgrind's 'massif' tool: 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// http://valgrind.org/docs/manual/ms-manual.html 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Here is an example command line: 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* valgrind --tool=massif --massif-out-file=massif.out \ 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ms_print massif.out 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)*/ 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// In addition: 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// * if PRINT_MEM_TRAFFIC is defined, all the details of the malloc/free cycles 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// are printed. 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// * if MALLOC_FAIL_AT is defined, the global environment variable 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// $MALLOC_FAIL_AT is used to simulate a memory error when calloc or malloc 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// is called for the nth time. Example usage: 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// export MALLOC_FAIL_AT=50 && ./examples/cwebp input.png 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// * if MALLOC_LIMIT is defined, the global environment variable $MALLOC_LIMIT 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// sets the maximum amount of memory (in bytes) made available to libwebp. 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// This can be used to emulate environment with very limited memory. 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Example: export MALLOC_LIMIT=64000000 && ./examples/dwebp picture.webp 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// #define PRINT_MEM_INFO 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// #define PRINT_MEM_TRAFFIC 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// #define MALLOC_FAIL_AT 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// #define MALLOC_LIMIT 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checked memory allocation 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(PRINT_MEM_INFO) 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdio.h> 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdlib.h> // for abort() 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int num_malloc_calls = 0; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int num_calloc_calls = 0; 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int num_free_calls = 0; 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int countdown_to_fail = 0; // 0 = off 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef struct MemBlock MemBlock; 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct MemBlock { 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void* ptr_; 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t size_; 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MemBlock* next_; 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static MemBlock* all_blocks = NULL; 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static size_t total_mem = 0; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static size_t total_mem_allocated = 0; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static size_t high_water_mark = 0; 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static size_t mem_limit = 0; 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int exit_registered = 0; 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void PrintMemInfo(void) { 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "\nMEMORY INFO:\n"); 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "num calls to: malloc = %4d\n", num_malloc_calls); 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, " calloc = %4d\n", num_calloc_calls); 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, " free = %4d\n", num_free_calls); 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "total_mem: %u\n", (uint32_t)total_mem); 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "total_mem allocated: %u\n", (uint32_t)total_mem_allocated); 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "high-water mark: %u\n", (uint32_t)high_water_mark); 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (all_blocks != NULL) { 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MemBlock* b = all_blocks; 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) all_blocks = b->next_; 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) free(b); 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void Increment(int* const v) { 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!exit_registered) { 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(MALLOC_FAIL_AT) 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char* const malloc_fail_at_str = getenv("MALLOC_FAIL_AT"); 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (malloc_fail_at_str != NULL) { 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) countdown_to_fail = atoi(malloc_fail_at_str); 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(MALLOC_LIMIT) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const char* const malloc_limit_str = getenv("MALLOC_LIMIT"); 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (malloc_limit_str != NULL) { 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mem_limit = atoi(malloc_limit_str); 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (void)countdown_to_fail; 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (void)mem_limit; 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) atexit(PrintMemInfo); 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exit_registered = 1; 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++*v; 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void AddMem(void* ptr, size_t size) { 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ptr != NULL) { 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MemBlock* const b = (MemBlock*)malloc(sizeof(*b)); 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (b == NULL) abort(); 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) b->next_ = all_blocks; 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) all_blocks = b; 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) b->ptr_ = ptr; 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) b->size_ = size; 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_mem += size; 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_mem_allocated += size; 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(PRINT_MEM_TRAFFIC) 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(MALLOC_FAIL_AT) 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "fail-count: %5d [mem=%u]\n", 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) num_malloc_calls + num_calloc_calls, (uint32_t)total_mem); 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "Mem: %u (+%u)\n", (uint32_t)total_mem, (uint32_t)size); 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (total_mem > high_water_mark) high_water_mark = total_mem; 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void SubMem(void* ptr) { 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ptr != NULL) { 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MemBlock** b = &all_blocks; 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Inefficient search, but that's just for debugging. 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (*b != NULL && (*b)->ptr_ != ptr) b = &(*b)->next_; 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (*b == NULL) { 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "Invalid pointer free! (%p)\n", ptr); 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) abort(); 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) { 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MemBlock* const block = *b; 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) *b = block->next_; 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_mem -= block->size_; 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(PRINT_MEM_TRAFFIC) 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fprintf(stderr, "Mem: %u (-%u)\n", 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (uint32_t)total_mem, (uint32_t)block->size_); 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) free(block); 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define Increment(v) do {} while(0) 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define AddMem(p, s) do {} while(0) 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define SubMem(p) do {} while(0) 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns 0 in case of overflow of nmemb * size. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64_t total_size = nmemb * size; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nmemb == 0) return 1; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((uint64_t)size > WEBP_MAX_ALLOCABLE_MEMORY / nmemb) return 0; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (total_size != (size_t)total_size) return 0; 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(PRINT_MEM_INFO) && defined(MALLOC_FAIL_AT) 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (countdown_to_fail > 0 && --countdown_to_fail == 0) { 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 0; // fake fail! 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(MALLOC_LIMIT) 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (mem_limit > 0 && total_mem + total_size >= mem_limit) { 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 0; // fake fail! 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* WebPSafeMalloc(uint64_t nmemb, size_t size) { 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void* ptr; 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Increment(&num_malloc_calls); 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(nmemb * size > 0); 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ptr = malloc((size_t)(nmemb * size)); 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddMem(ptr, (size_t)(nmemb * size)); 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ptr; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* WebPSafeCalloc(uint64_t nmemb, size_t size) { 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void* ptr; 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Increment(&num_calloc_calls); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CheckSizeArgumentsOverflow(nmemb, size)) return NULL; 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(nmemb * size > 0); 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ptr = calloc((size_t)nmemb, size); 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) AddMem(ptr, (size_t)(nmemb * size)); 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ptr; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void WebPSafeFree(void* const ptr) { 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ptr != NULL) { 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Increment(&num_free_calls); 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SubMem(ptr); 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) free(ptr); 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//------------------------------------------------------------------------------ 212