MiniGUI使用之关于皮肤窗口的skin_init和skin_deinit的疑问
2009-06-08 10:21
495 查看
关于皮肤窗口的skin_init和skin_deinit的疑问?
最近学习使用MiniGUI的皮肤窗口,在使用标签控件过程中出现了一些奇怪的问题:
为了使用图片标签,我在一个子窗口模块中定义了一个模块级的si_bmplabel_t变量。按照通常程序我对skin_head_t进行了声明,然后调用skin_init进行了初始化,显示窗口,操作一番,退出时,由于skin_head_t变量是动态创建的,于是对其进行释放,释放前我调用了skin_deinit。一切都很正常,但是在我尝试第二次进入这个窗口时,问题出现了,标签显示不正常。为了搞清楚原因对MiniGUI源码进行了跟踪。原来是MiniGUI在skin_init和skin_deinit中的处理导致了模块级变量属性的意外丢失。
首先来看一下si_bmplabel_t的定义:
typedef struct si_bmplabel_s
{
/** The label string. */
char* label;
/** All label characters in the bitmap. */
const char* label_chars;
} si_bmplabel_t;
其中,label记录着标签的显示值,label_chars记录的是标签所使用的字符图片的字符序列。
在skin_init中针对图片标签会进行特殊的初始化,该初始化由下面这个函数完成:
static int bmplabel_init (skin_head_t* skin, skin_item_t *item)
{
DECL_LABEL ( si_bmplabel_t, 0);
//注意下面这句:
mylabel->label = strdup ( mylabel->label ? mylabel->label : EMPTY );
return 1;
}
DECL_LABEL的定义如下:
#define DECL_LABEL(type,ret) /
type *mylabel = (type *) item->type_data; /
if (!mylabel) return ret;
这个函数干了什么事情呢?它将item的type_data属性转变为一个si_bmplabel_t的指针,然后把这个si_bmplabel_t变量的label复制一遍再赋给这个label。也就是说原来的那个label记录的指针已经丢失了。如果这个label指向的是一个动态申请的字符串,而代码中恰好没有其他的指针指向它,那么很遗憾,这段内存已经泄漏。
再来看看MiniGUI中skin_deinit和skin_set_item_label都干了什么:
skin_deinit会调用下面这个函数对标签属性进行释放,
static int bmplabel_deinit (skin_item_t *item)
{
DECL_LABEL ( si_bmplabel_t, 0);
if (mylabel->label) free (mylabel->label);
return 1;
}
skin_set_item_label调用set_label函数实现对标签属性的设置。
在set_label (skin_item_t *item, DWORD label)函数中下面的代码则负责对原label指向字符串的释放:
if (mylabel->label) free (mylabel->label);
mylabel->label = strdup (new_label);
MiniGUI对自己还是很负责的,进行了复制,当然要进行释放了。
不过,遗憾的是,这么一去一来,调用skin_deinit进行皮肤释放后,用户自己定义的si_bmplabel_t变量的label也一起被释放了。别忘了这个label指针仍然尽职尽责的指向最后strdup复制的字符串,尽管这个字符串已经被skin_deinit释放了。
既然MiniGUI为了防止外部代码对控件内部属性的直接访问(实际上skin_set_item_label还要做很多事以确保显示的正确性)。是不是也应该考虑这么做对外部代码的影响。或者干脆就直接对si_bmplabel_t变量进行复制,这样不是更保险么?
最近学习使用MiniGUI的皮肤窗口,在使用标签控件过程中出现了一些奇怪的问题:
为了使用图片标签,我在一个子窗口模块中定义了一个模块级的si_bmplabel_t变量。按照通常程序我对skin_head_t进行了声明,然后调用skin_init进行了初始化,显示窗口,操作一番,退出时,由于skin_head_t变量是动态创建的,于是对其进行释放,释放前我调用了skin_deinit。一切都很正常,但是在我尝试第二次进入这个窗口时,问题出现了,标签显示不正常。为了搞清楚原因对MiniGUI源码进行了跟踪。原来是MiniGUI在skin_init和skin_deinit中的处理导致了模块级变量属性的意外丢失。
首先来看一下si_bmplabel_t的定义:
typedef struct si_bmplabel_s
{
/** The label string. */
char* label;
/** All label characters in the bitmap. */
const char* label_chars;
} si_bmplabel_t;
其中,label记录着标签的显示值,label_chars记录的是标签所使用的字符图片的字符序列。
在skin_init中针对图片标签会进行特殊的初始化,该初始化由下面这个函数完成:
static int bmplabel_init (skin_head_t* skin, skin_item_t *item)
{
DECL_LABEL ( si_bmplabel_t, 0);
//注意下面这句:
mylabel->label = strdup ( mylabel->label ? mylabel->label : EMPTY );
return 1;
}
DECL_LABEL的定义如下:
#define DECL_LABEL(type,ret) /
type *mylabel = (type *) item->type_data; /
if (!mylabel) return ret;
这个函数干了什么事情呢?它将item的type_data属性转变为一个si_bmplabel_t的指针,然后把这个si_bmplabel_t变量的label复制一遍再赋给这个label。也就是说原来的那个label记录的指针已经丢失了。如果这个label指向的是一个动态申请的字符串,而代码中恰好没有其他的指针指向它,那么很遗憾,这段内存已经泄漏。
再来看看MiniGUI中skin_deinit和skin_set_item_label都干了什么:
skin_deinit会调用下面这个函数对标签属性进行释放,
static int bmplabel_deinit (skin_item_t *item)
{
DECL_LABEL ( si_bmplabel_t, 0);
if (mylabel->label) free (mylabel->label);
return 1;
}
skin_set_item_label调用set_label函数实现对标签属性的设置。
在set_label (skin_item_t *item, DWORD label)函数中下面的代码则负责对原label指向字符串的释放:
if (mylabel->label) free (mylabel->label);
mylabel->label = strdup (new_label);
MiniGUI对自己还是很负责的,进行了复制,当然要进行释放了。
不过,遗憾的是,这么一去一来,调用skin_deinit进行皮肤释放后,用户自己定义的si_bmplabel_t变量的label也一起被释放了。别忘了这个label指针仍然尽职尽责的指向最后strdup复制的字符串,尽管这个字符串已经被skin_deinit释放了。
既然MiniGUI为了防止外部代码对控件内部属性的直接访问(实际上skin_set_item_label还要做很多事以确保显示的正确性)。是不是也应该考虑这么做对外部代码的影响。或者干脆就直接对si_bmplabel_t变量进行复制,这样不是更保险么?
相关文章推荐
- 关于minigui的皮肤窗口
- 关于minigui的皮肤控件无法显示问题
- 关于Access发布使用打包软件的一些疑问解答
- c# WinForm 窗体美化(二)--关于东日skinbuilder软件生成皮肤的使用
- SKIN++皮肤的使用
- bcb使用com是导入类型库和使用Vclskin皮肤
- VC皮肤库SkinSharp 1.0.6.6的使用
- VC皮肤库SkinSharp 1.0.6.6的使用
- 关于__no_init等关键字的一些疑问
- Flex4中的皮肤(4):使用SkinPart约束Skin
- 【VC皮肤】破解版skin++皮肤库使用
- 关于C#替换Word文本框中的内容(不使用Bookmark)疑问
- 2007-11-28 MiniGUI皮肤界面普通标签的使用
- 关于在窗口消息处理函数中使用MessageBox造成消息重入的问题的研究及解决
- SkinSB皮肤滚动条库的使用
- 使用IrisSkin2.dll (SkinEngine) 加载C# WinForm界面皮肤
- 关于okhttp和retrofit的使用的疑问
- VC皮肤库SkinSharp 1.0.6.6的使用
- 关于使用vc进行换肤设置和使用skinplusplus.dll美化界面
- 关于Web中使用模态对话框时向父窗口中的控件赋值