int ly_write(struct lyout *out, const char *buf, size_t count) { if (out->hole_count) { /* we are buffering data after a hole */ if (out->buf_len + count > out->buf_size) { out->buffered = ly_realloc(out->buffered, out->buf_len + count); if (!out->buffered) { out->buf_len = 0; out->buf_size = 0; LOGMEM(NULL); return -1; } out->buf_size = out->buf_len + count; } memcpy(&out->buffered[out->buf_len], buf, count); out->buf_len += count; return count; } switch (out->type) { case LYOUT_MEMORY: if (out->method.mem.len + count + 1 > out->method.mem.size) { out->method.mem.buf = ly_realloc(out->method.mem.buf, out->method.mem.len + count + 1); if (!out->method.mem.buf) { out->method.mem.len = 0; out->method.mem.size = 0; LOGMEM(NULL); return -1; } out->method.mem.size = out->method.mem.len + count + 1; } memcpy(&out->method.mem.buf[out->method.mem.len], buf, count); out->method.mem.len += count; out->method.mem.buf[out->method.mem.len] = '\0'; return count; case LYOUT_FD: return write(out->method.fd, buf, count); case LYOUT_STREAM: return fwrite(buf, sizeof *buf, count, out->method.f); case LYOUT_CALLBACK: return out->method.clb.f(out->method.clb.arg, buf, count); } return 0; }
DETOUR_DECL_MEMBER(void, CWaveDataStreamAsync_dtor, uint32_t i1) { std::lock_guard<std::mutex> lock(m_CWaveDataStreamAsync); --num_CWaveDataStreamAsync; LOGMEM("--- CWaveDataStreamAsync @ 0x%08x [total: %d]\n", (uintptr_t)this, num_CWaveDataStreamAsync); DETOUR_MEMBER_CALL(CWaveDataStreamAsync_dtor)(i1); }
DETOUR_DECL_MEMBER(void, CWaveDataStreamAsync_ctor, uint32_t r1, uint32_t p1, const char *s1, int i1, int i2, uint32_t p2, int i3) { std::lock_guard<std::mutex> lock(m_CWaveDataStreamAsync); ++num_CWaveDataStreamAsync; LOGMEM("+++ CWaveDataStreamAsync @ 0x%08x [total: %d]\n", (uintptr_t)this, num_CWaveDataStreamAsync); DETOUR_MEMBER_CALL(CWaveDataStreamAsync_ctor)(r1, p1, s1, i1, i2, p2, i3); }
DETOUR_DECL_MEMBER(void, CAudioMixerWaveMP3_dtor, uint32_t i1) { std::lock_guard<std::mutex> lock(m_CAudioMixerWaveMP3); --num_CAudioMixerWaveMP3; LOGMEM("--- CAudioMixerWaveMP3 @ 0x%08x [total: %d]\n", (uintptr_t)this, num_CAudioMixerWaveMP3); DETOUR_MEMBER_CALL(CAudioMixerWaveMP3_dtor)(i1); }
int ly_print(struct lyout *out, const char *format, ...) { int count = 0; char *msg = NULL, *aux; va_list ap; #ifndef HAVE_VDPRINTF FILE *stream; #endif va_start(ap, format); switch (out->type) { case LYOUT_FD: #ifdef HAVE_VDPRINTF count = vdprintf(out->method.fd, format, ap); #else stream = fdopen(dup(out->method.fd), "a+"); if (stream) { count = vfprintf(stream, format, ap); fclose(stream); } #endif break; case LYOUT_STREAM: count = vfprintf(out->method.f, format, ap); break; case LYOUT_MEMORY: count = vasprintf(&msg, format, ap); if (out->method.mem.len + count + 1 > out->method.mem.size) { aux = ly_realloc(out->method.mem.buf, out->method.mem.len + count + 1); if (!aux) { out->method.mem.buf = NULL; out->method.mem.len = 0; out->method.mem.size = 0; LOGMEM(NULL); va_end(ap); return -1; } out->method.mem.buf = aux; out->method.mem.size = out->method.mem.len + count + 1; } memcpy(&out->method.mem.buf[out->method.mem.len], msg, count); out->method.mem.len += count; out->method.mem.buf[out->method.mem.len] = '\0'; free(msg); break; case LYOUT_CALLBACK: count = vasprintf(&msg, format, ap); count = out->method.clb.f(out->method.clb.arg, msg, count); free(msg); break; } va_end(ap); return count; }
void Mem_End() { if (!mem_tracking) return; mem_tracking = false; size_t total = 0; LOGMEM( "================================================================================\n" "Memory leak report:\n" "================================================================================\n"); for (const auto& pair : mems) { const void *ptr = pair.first; size_t size = pair.second; LOGMEM("0x%08x: %u bytes\n", (uintptr_t)ptr, size); total += size; } LOGMEM( "================================================================================\n" "Total memory leaked: %u bytes\n" "================================================================================\n", total); }
DETOUR_DECL_MEMBER(void *, IMemAlloc_Alloc, size_t nSize) { std::lock_guard<std::mutex> lock(m_Alloc); SCOPED_INCREMENT(rc_Alloc); auto result = DETOUR_MEMBER_CALL(IMemAlloc_Alloc)(nSize); if (mem_tracking && rc_Alloc <= 1 && nSize >= cvar_minimum.GetInt()) { if (mems.find(result) == mems.end()) { LOGMEM("[%12.7f] Alloc %7u @ 0x%08x\n", Plat_FloatTime(), nSize, (uintptr_t)result); mems[result] = nSize; } else { Warning("IMemAlloc::Alloc(0x%08x, %u): pointer already in map!\n", (uintptr_t)result, nSize); } // if (cvar_alloc.GetBool()) { // LOGMEM("[%12.7f] Alloc %7u @ 0x%08x\n", Plat_FloatTime(), nSize, (uintptr_t)result); // } } return result; }
DETOUR_DECL_MEMBER(void, IMemAlloc_Free, void *pMem) { std::lock_guard<std::mutex> lock(m_Free); SCOPED_INCREMENT(rc_Free); if (pMem == nullptr) return; if (mem_tracking && rc_Free <= 1) { auto it = mems.find(pMem); if (it != mems.end()) { LOGMEM("[%12.7f] Free %7u @ 0x%08x\n", Plat_FloatTime(), (*it).second, (uintptr_t)pMem); mems.erase(it); } else { // Warning("IMemAlloc::Free: deallocation of untracked pointer!\n"); } // if (cvar_free.GetBool()) { // LOGMEM("[%12.7f] Free 0x%08x\n", Plat_FloatTime(), (uintptr_t)pMem); // } } DETOUR_MEMBER_CALL(IMemAlloc_Free)(pMem); }
static int lyb_read_start_subtree(const char *data, struct lyb_state *lybs) { uint8_t meta_buf[LYB_META_BYTES]; if (lybs->used == lybs->size) { lybs->size += LYB_STATE_STEP; lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written); lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position); lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks); LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(NULL), -1); } memcpy(meta_buf, data, LYB_META_BYTES); ++lybs->used; lybs->written[lybs->used - 1] = meta_buf[0]; lybs->inner_chunks[lybs->used - 1] = meta_buf[LYB_SIZE_BYTES]; lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0); return LYB_META_BYTES; }
virtual void FrameUpdatePostEntityThink() { LOGMEM("FrameUpdatePostEntityThink\n"); Mem_End(); }
virtual void FrameUpdatePreEntityThink() { LOGMEM("FrameUpdatePreEntityThink\n"); // Mem_End(); }