找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 4796|回复: 0

【分享】#pragma data_seg说明

[复制链接]

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2009-3-7 11:48:23 | 显示全部楼层 |阅读模式
<p><font face="Verdana"><font style="BACKGROUND-COLOR: #ffffff" color="#0000ff" face="Verdana">#pragma data_seg介绍 <br/>&nbsp;&nbsp; 用#pragma data_seg建立一个新的数据段并定义共享数据,其具体格式为: <br/>  #pragma data_seg ("shareddata") <br/>  HWND sharedwnd=NULL;//共享数据 <br/>  #pragma data_seg()&nbsp;&nbsp; <br/>-----------------------------------------------------------------------------------------------------<br/>1,#pragma data_seg()一般用于DLL中。也就是说,在DLL中定义一个共享的,有名字的数据段。最关键的是:这个数据段中的全局变量可以被多个进程共享。否则多个进程之间无法共享DLL中的全局变量。<br/>2,共享数据必须初始化,否则微软编译器会把没有初始化的数据放到.BSS段中,从而导致多个进程之间的共享行为失败。<br/>3,你所谓的结果正确是一种错觉。如果你在一个DLL中这么写:<br/>#pragma data_seg("MyData")<br/>int g_Value; // Note that the global is not initialized.<br/>#pragma data_seg()<br/>DLL提供两个接口函数:<br/>int GetValue()<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return g_Value;<br/>}<br/>void SetValue(int n)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g_Value = n;<br/>}<br/>然后启动两个进程A和B,A和B都调用了这个DLL,假如A调用了SetValue(5); B接着调用int m = GetValue(); 那么m的值不一定是5,而是一个未定义的值。因为DLL中的全局数据对于每一个调用它的进程而言,是私有的,不能共享的。假如你对g_Value进行了初始化,那么g_Value就一定会被放进MyData段中。换句话说,如果A调用了SetValue(5); B接着调用int m = GetValue(); 那么m的值就一定是5!这就实现了跨进程之间的数据通信!</font></font></p>
<p><font face="Verdana"></font>&nbsp;</p>
<p><font face="Verdana">有的时候我们可能想让一个应用程序只启动一次,就像单件模式(singleton)一样,实现的方法可能有多种,这里说说用#pragma data_seg来实现的方法,很是简洁便利。</font></p>
<p><font face="Verdana">应用程序的入口文件前面加上</font></p>
<p><font face="Verdana">#pragma data_seg("flag_data")<br/>int app_count = 0;<br/>#pragma data_seg()<br/>#pragma comment(linker,"/SECTION:flag_data,RWS")</font></p>
<p><font face="Verdana">然后程序启动的地方加上</font></p>
<p><font face="Verdana">if(app_count&gt;0)&nbsp;&nbsp;&nbsp;&nbsp; // 如果计数大于0,则退出应用程序。<br/>{<br/>&nbsp;&nbsp; //MessageBox(NULL, "已经启动一个应用程序", "Warning", MB_OK);</font></p>
<p><font face="Verdana">&nbsp;&nbsp; //printf("no%d application", app_count);</font></p>
<p><font face="Verdana">&nbsp;&nbsp; return FALSE;<br/>}<br/>app_count++;</font></p><font face="Verdana">
<p><br/>Windows在一个Win32程序的地址空间周围筑了一道墙。通常,一个程序的地址空间中的数据是私有的,对别的程序而言是不可见的。但是执行STRPROG的多个执行实体表示了STRLIB在程序的所有执行实体之间共享数据是毫无问题的。当您在一个STRPROG窗口中增加或者删除一个字符串时,这种改变将立即反映在其它的窗口中。</p>
<p>在全部例程之间,STRLIB共享两个变量:一个字符数组和一个整数(记录已储存的有效字符串的个数)。STRLIB将这两个变量储存在共享的一个特殊内存区段中:</p>
<p>#pragma&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data_seg ("shared")<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iTotal = 0 ;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>WCHAR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; szStrings [MAX_STRINGS][MAX_LENGTH + 1] = { '\0' } ;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>#pragma&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data_seg ()<br/>&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>第一个#pragma叙述建立数据段,这里命名为shared。您可以将这段命名为任何一个您喜欢的名字。在这里的#pragma叙述之后的所有初始化了的变量都放在shared数据段中。第二个#pragma叙述标示段的结束。对变量进行专门的初始化是很重要的,否则编译器将把它们放在普通的未初始化数据段中而不是放在shared中。</p>
<p>连结器必须知道有一个「shared」共享数据段。在「Project Settings」对话框选择「Link」页面卷标。选中「STRLIB」时在「Project Options」字段(在Release和Debug设定中均可),包含下面的连结叙述:</p>
<p>/SECTION:shared,RWS<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>字母RWS表示段具有读、写和共享属性。或者,您也可以直接用DLL原始码指定连结选项,就像我们在STRLIB.C那样:</p>
<p>#pragma comment(linker,"/SECTION:shared,RWS")<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br/>共享的内存段允许iTotal变量和szStrings字符串数组在STRLIB的所有例程之间共享。因为MAX_STRINGS等于256,而MAX_LENGTH等于63,所以,共享内存段的长度为32,772字节-iTotal变量需要4字节,256个指针中的每一个都需要128字节。<br/></font></p>
[此贴子已经被作者于2009-3-7 12:10:43编辑过]
【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表