现在的位置: 首页 > 综合 > 正文

从 “specified with /SECTION option does not exist” 说开

2012年01月29日 ⁄ 综合 ⁄ 共 1465字 ⁄ 字号 评论关闭

      这是使用共享内存节的一个经典错误,共享内存节,简称共享节用于dll在多个进程中共享变量或者多个实例间共享变量。

      首先说说共享节的使用方法:

      #pragma data_seg(".SharedMem")

            BOOL g_bOpenUse = FALSE;

      #pragma data_seg()

      #pragma comment(linker,"/SECTION:.SharedMem,RWS")

 

      前面两个#pragma是声明一个数据段,之间定义的变量既是放入该数据段的数据,最后的#pragma comment是告诉链接器该段是一个是可读可写的共享段,做完这几步就可以使dll在多进程中共享数据,dll程序还可以在*.def中间声明SECTIONS .SharedMem READ WRITE SHARED达到告诉链接器这是共享段的目的(可以省略#pragma comment(linker,"/SECTION:.SharedMem,RWS")这句,但是对于exe程序,则只能使用#pragma comment来声明共享段),这样就可以达到在一个进程中修改了数据,另外一个进程的数据也修改了的目的。

      使用共享节要注意的一些问题

      1、在dll中使用共享节的时候要注意,如果dll第一次被加载后,修改了共享节中变量的值,但是在该dll第二次被加载之前,前一次被加载的dll被卸载了,那么该dll第二次加载时肯定又要重新初始化共享节中的数据,所以这里的问题就是如果你要长时间共享数据,应该保证多次加载的dll长时间在响应的进程内。

      2、不要在共享节中定义指针指向dll中某个数据,因为每个进程都有自己的虚拟地址空间,同一个地址在不同的进程中表示的数据显然是不同的。同理,特定于一个进程的一些信息放入共享节中也是没有意义的。

      3、再就是最好不要在共享节中放入类实例,微软也不建议做,具有虚函数的类都是有虚指针的,同时,类都有自己的构造函数,它是一个函数,那么每次都会调用,相当把原来的数据就清理了,这和基本数据类型被链接器在链接的时候就初始化是不同的。

      4、如果是多进程同步修改读取,则要加锁机制


      再看看标题的那个错误,发生这个问题有几种原因:

      1、语法写错了,这个就要仔细检查了;

      2、共享节的名字过长,上面那个共享节的名字是.SharedMem,长度不能超过32个字符,如果长度超过32,编译器在创建数据段的时候会截断名字到只剩下前面32个字符,链接器去按原来的名字去找数据段的时候自然找不到了。

      3、共享节中的数据都要初始化,如果不初始化,会被编译器放到.bss段中去,如果所有的数据都没初始化,那么这个数据段相当于没有数据了,编译器根本不会创建这个段,链接器也会找不到;如果一部分初始化了,那更悲剧了,编译链接都没有问题,但是你会发现有些变量貌似没有共享哦。^_^

[end]


     调用dll中的函数时出现错误:Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call,这个一般是因为调用者声明的函数调用类型和dll中被调用函数的函数调用类型不一致造成的, 也就是你定义的函数指针原型和dll真正函数的原型有点不一样,假如你声明的调用类型是__cedcall,而dll中声明的函数调用类型是__stdcall,错误就发生了。

抱歉!评论已关闭.