add gb_json life monitor; fix mem-leak when update_data

This commit is contained in:
gb 2023-11-13 17:48:05 +08:00
parent d5b90ef03b
commit 02abb23198
6 changed files with 156 additions and 15 deletions

View File

@ -956,7 +956,7 @@ scanner_err hg_scanner_mgr::hg_scanner_get_parameter(scanner_handle h, const cha
device_option* tmp = nullptr;
if (!h)
{
device_option* tmp = new device_option();
tmp = new device_option();
tmp->add(offline_);
tmp->add(g_language);

View File

@ -420,6 +420,8 @@ extern "C"
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{
//static _CrtMemState state;
if (reason == DLL_PROCESS_ATTACH)
{
//if (g_scanner_path.empty())
@ -433,6 +435,9 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
// g_scanner_path = path;
// }
//}
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
}
return TRUE;

View File

@ -119,3 +119,85 @@ extern "C" { // avoid compiler exporting name in C++ style !!!
}
#if defined(WIN32) || defined(_WIN64)
#include <json/gb_json.h>
#include <vector>
#include <algorithm>
typedef struct _jsn_obj
{
gb_json* jsn;
int from;
bool operator==(const gb_json* obj)
{
return jsn == obj;
}
}JSNOBJ;
static std::vector<JSNOBJ> g_jsn_objs;
static int max_objs = 0;
static void record_json(gb_json* jsn, bool add, void* param)
{
std::vector<JSNOBJ>::iterator it = std::find(g_jsn_objs.begin(), g_jsn_objs.end(), jsn);
if (it == g_jsn_objs.end())
{
if (add)
{
JSNOBJ jo;
DWORD base = 0;
_asm
{
push eax
mov eax, ebp
mov base, eax
pop eax
}
jo.jsn = jsn;
jo.from = ((DWORD***)base)[0][0][1];
g_jsn_objs.push_back(jo);
if (max_objs < g_jsn_objs.size())
max_objs = g_jsn_objs.size();
}
}
else if (!add)
g_jsn_objs.erase(it);
}
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
{
//static _CrtMemState state;
if (reason == DLL_PROCESS_ATTACH)
{
//if (g_scanner_path.empty())
//{
// char path[MAX_PATH] = { 0 };
// GetModuleFileNameA(inst, path, _countof(path) - 1);
//// if (strrchr(path, '\\'))
// {
//// strrchr(path, '\\')[1] = 0;
// g_scanner_path = path;
// }
//}
//_CrtMemCheckpoint(&state);
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetBreakAlloc(632555577);
set_gbjson_life_callback(record_json, nullptr);
#endif
}
else if (reason == DLL_PROCESS_DETACH)
{
#ifdef _DEBUG
_CrtDumpMemoryLeaks();
#endif
//_CrtMemDumpAllObjectsSince(&state);
}
return TRUE;
}
#endif

View File

@ -1,5 +1,5 @@
#include "gb_json.h"
#include "cJSON.h"
#include <stdlib.h>
#include <string.h>
@ -82,31 +82,79 @@ namespace special_char_trans
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// life callback ...
#ifdef DUMP_JSON_OBJECT_LIFE
static void record_life_empty(gb_json*, bool, void*)
{}
static void(*g_life)(gb_json*, bool, void*) = &record_life_empty;
static void* g_life_param = nullptr;
void set_gbjson_life_callback(void(*life)(gb_json*, bool, void*), void* param)
{
g_life_param = param;
g_life = life ? life : &record_life_empty;
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// gb_json ...
gb_json::gb_json(char* json_txt) : ref_(1), type_(VAL_TYPE_OBJECT), key_(""), strval_(""), cur_child_(-1)
{
#ifdef DUMP_JSON_OBJECT_LIFE
g_life(this, true, g_life_param);
#endif
simple_val_.dval = .0f;
if(json_txt)
attach_text(json_txt);
}
gb_json::gb_json(const char* key, bool val) : ref_(1), type_(VAL_TYPE_BOOL), key_(key ? key : ""), strval_(""), cur_child_(-1)
{
#ifdef DUMP_JSON_OBJECT_LIFE
g_life(this, true, g_life_param);
#endif
simple_val_.bval = val;
}
gb_json::gb_json(const char* key, int val) : ref_(1), type_(VAL_TYPE_INT), key_(key ? key : ""), strval_(""), cur_child_(-1)
{
#ifdef DUMP_JSON_OBJECT_LIFE
g_life(this, true, g_life_param);
#endif
simple_val_.nval = val;
}
gb_json::gb_json(const char* key, double val) : ref_(1), type_(VAL_TYPE_FLOAT), key_(key ? key : ""), strval_(""), cur_child_(-1)
{
#ifdef DUMP_JSON_OBJECT_LIFE
g_life(this, true, g_life_param);
#endif
simple_val_.dval = val;
}
gb_json::gb_json(const char* key, const char* val) : ref_(1), type_(VAL_TYPE_STRING), key_(key ? key : ""), strval_(val ? val : ""), cur_child_(-1)
{}
{
#ifdef DUMP_JSON_OBJECT_LIFE
g_life(this, true, g_life_param);
#endif
}
gb_json::gb_json(const char* key, const std::string& val) : ref_(1), type_(VAL_TYPE_STRING), key_(key ? key : ""), strval_(val), cur_child_(-1)
{}
{
#ifdef DUMP_JSON_OBJECT_LIFE
g_life(this, true, g_life_param);
#endif
}
gb_json::~gb_json()
{
clear();
#ifdef DUMP_JSON_OBJECT_LIFE
g_life(this, false, g_life_param);
#endif
}
std::string gb_json::object_key(gb_json* jsn)

View File

@ -116,3 +116,7 @@ public:
bool operator==(const gb_json& r);
bool operator!=(const gb_json& r);
};
#ifdef DUMP_JSON_OBJECT_LIFE
void set_gbjson_life_callback(void(*life)(gb_json*, bool, void*), void* param);
#endif

View File

@ -1687,10 +1687,8 @@ int device_option::update_data(const char* name, void* value, bool reorder_if_ne
{
bool ro = false;
if ((child->get_value("readonly", ro) && ro)
|| (child->get_value("auth", err) && !user_(err)))
|| (child->get_value("auth", err) && user_ && !user_(err)))
{
child->release();
err = SCANNER_ERR_ACCESS_DENIED;
}
else
@ -1718,7 +1716,8 @@ int device_option::update_data(const char* name, void* value, bool reorder_if_ne
}
if (err == SCANNER_ERR_OK || err == SCANNER_ERR_NOT_EXACT
|| err == SCANNER_ERR_RELOAD_IMAGE_PARAM || err == SCANNER_ERR_RELOAD_OPT_PARAM)
|| err == SCANNER_ERR_RELOAD_IMAGE_PARAM || err == SCANNER_ERR_RELOAD_OPT_PARAM
|| err == SCANNER_ERR_CONFIGURATION_CHANGED)
{
child->get_value("type", type);
if (type == JSON_SANE_TYPE_BOOL)
@ -1741,7 +1740,6 @@ int device_option::update_data(const char* name, void* value, bool reorder_if_ne
child->set_value("cur", (char*)value);
changed = pre != (char*)value;
}
child->release();
// set paper-w and paper-h
if (strcmp(name, SANE_STD_OPT_NAME_PAPER) == 0 ||
@ -1750,19 +1748,20 @@ int device_option::update_data(const char* name, void* value, bool reorder_if_ne
if (src_.count(SANE_STD_OPT_NAME_PAPER_W))
{
std::string w(src_[SANE_STD_OPT_NAME_PAPER_W]->get_value(SANE_STD_OPT_NAME_PAPER_W, nullptr)),
h(src_[SANE_STD_OPT_NAME_PAPER_H]->get_value(SANE_STD_OPT_NAME_PAPER_H, nullptr)),
lateral(get_option_value(SANE_STD_OPT_NAME_LATERAL, SANE_ACTION_GET_VALUE));
h(src_[SANE_STD_OPT_NAME_PAPER_H]->get_value(SANE_STD_OPT_NAME_PAPER_H, nullptr)),
lateral(get_option_value(SANE_STD_OPT_NAME_LATERAL, SANE_ACTION_GET_VALUE));
gb_json *jsnl = nullptr;
now_->get_value(SANE_STD_OPT_NAME_LATERAL, child);
if (child)
now_->get_value(SANE_STD_OPT_NAME_LATERAL, jsnl);
if (jsnl)
{
if (device_option::is_opt_enabled(child, nullptr, nullptr, nullptr))
if (device_option::is_opt_enabled(jsnl, nullptr, nullptr, nullptr))
{
refine_data(SANE_STD_OPT_NAME_LATERAL, &lateral[0]);
if (*(bool*)&lateral[0])
w.swap(h);
}
child->release();
jsnl->release();
}
gb_json* pw = nullptr,
@ -1798,6 +1797,9 @@ int device_option::update_data(const char* name, void* value, bool reorder_if_ne
}
} // provider has processed right
} // not read-only option
child->release();
} // has option named 'name'
} // has initialized