- 先需要明白一个问题:
COW:写时复制,即:Copy-on-Write,当写入时,进行拷贝:
无写入操作:共用一份内存
有写入操作:拷贝该块出来供修改,并改变进程的内存地址映射,使之映射到到新的内存块地址
这是一种内存优化策略,因为,当同一个EXE,或者同一个DLL执行的时候,程序段自然都是相同的;而在调用函数的时候压入栈的数据段,有可能也是相同的,假如确实是相同的,则操作系统会将不同的进程的相同内存块的部分映射到同一地址,其实,程序的执行无论代码或者数据,都是基于地址的,操作系统则可以通过合理的管理这些地址,进行内存空间的优化。还有另一种情况是,假如数据段被某个或者某些进程修改了怎么办呢?此时,会根据COW原则,对有修改操作的进程,将它们对该内存的控制权取消,转移到另一块内存去进行操作,避免造成共享内存数据的不一致性。关于全局函数和静态变量,他们在下面这个问题上是等价的:就是只能在一个进程内部共享,而不会和另一个进程共享,因此,不同进程对于同一个DLL中全局或者静态变量的修改,会导致系统给它专门分配一块新的空间出来。
- 那么就有一个问题了:
如何通过一个DLL去实现进程间的数据共享呢?
有一种声明,导出,载入共享数据段的方式,但是似乎这种方法并不可行,或者说,最起码,不被推崇。
而最受欢迎的是mmap/munmap方法,多个进程,将同一个文件,映射到内存,此时,他们能(宏观上)同时对该内存进行读写操作,进而完成数据共享。
- 虚函数,静态函数,成员函数:是否放在代码区同等的位置:
是的,都放在类作用域内(区别于对象的作用域:对象的作用域是指对象所占的堆栈空间);类的作用域空间无非是该类的常量空间,静态变量空间,代码空间(唯独没有堆栈等数据空间)。
由此也可知一个问题:内存分为堆、栈、代码、静态、常量,共五类空间。
- static函数的问题:
另一个问题:类中static函数的问题:非static函数都会使用__thiscall方法调用,该方法实质会传入this指针作为参数,将函数中的变量重新映射到实例对应的数据区,从而对实例的成员变量进行访问;然而,static方法不会传入this指针,因此他无法访问成员函数,虚函数必须能访问虚函数表,这个表指针是存放在实例空间中的,因此虚函数不能是static方法,否则无法访问虚函数表。
- 虚函数表具体存放在什么位置:
存放在类作用域的常量区。
- 那些数据是放在类作用域的内存空间,那些数据是放在对象的内存空间:
成员函数代码,静态函数代码,虚函数代码,静态变量,常量,虚函数表:存放在类定义区;
虚函数表指针,成员变量:放在对象实例区。
做个实验:
修改两个不同类的“虚函数表指针”,看看是否如期望的那样:对象初始的4个字节存放“虚函数表”
代码:
1 #include2 3 /*** 4 * @author:zanzan101 5 */ 6 7 class A 8 { 9 private:10 int data;11 public:12 virtual int foo()13 {14 printf("A\n");15 return 1;16 }17 };18 19 class B : public A20 {21 public:22 int foo()23 {24 printf("B\n");25 return 2;26 }27 };28 29 class C : public A30 {31 public:32 int foo()33 {34 printf("C\n");35 return 3;36 }37 };38 39 void func(const char* str)40 {41 printf("%s\n", str);42 }43 44 typedef void (*ptr_of_func)(const char *); // 这是个类型定义45 ptr_of_func p = func; // 这是个变量声明及初始化46 47 // 分开操作则报错48 // ptr_of_func q;49 // q = func;50 51 int main()52 {53 C c;54 B b;55 A* ptr = &b;56 if(2 == ptr->foo())57 p("多态:调用了B的函数!");58 59 // 修改B的对象的前4个字节的数据为C对象的前4个字节的数据60 p("修改B的对象的前4个字节的数据为C对象的前4个字节的数据");61 memcpy(&b, &c, sizeof(void*));62 63 if(3 == ptr->foo())64 p("虚函数表指针被修改了!");65 66 system("pause");67 return 0;68 }
输出:
B多态:调用了B的函数!修改B的对象的前4个字节的数据为C对象的前4个字节的数据C虚函数表指针被修改了!请按任意键继续. . .
>>转载请注明出处<<