我知道动态加载的库共享相同的地址空间但我不确定当我在动态加载的库中分配内存并关闭库时会发生什么。当对象不是加载库的一部分时,分配的对象是否仍然有效?例如一个简单的std :: string或我的任何类?
答案 0 :(得分:3)
(我采用Linux的观点; C ++ 14标准不了解动态加载库)
运行C ++程序的整个heap只有一个virtual address space(和一个process)。因此,在较低级别,可以在同一进程中从一个库lib1.so
分配内存区域,并从另一个库lib2.so
中释放内存区域。
您可以使用相同的共享库创建多个进程;然后,在几个进程之间有效地共享该库的文本或code segment(而不是数据段)。
其余的是编程约定。五条规则(之前是rule of three)是C ++中非常有用的约定
在内部使用mmap(2),可以使用/proc/$PID/maps
查看地址空间(请参阅proc(5))。因此,对于pid 1234的进程尝试在终端中运行cat /proc/1234/maps
,您将了解更多如何在该进程的虚拟地址空间中加载共享库。
答案 1 :(得分:1)
当对象不是加载库的一部分时,分配的对象是否仍然有效?
可能。
在UNIX系统上,不包含任何指向已加载库的指针的堆分配对象肯定是有效的(因为堆是一个进程全局资源)。
但是,在C++
中,堆分配的对象可能包含一个虚拟表指针,该指针将指向共享库中的.code
,如果此类库已完全卸载,则此虚拟表指针会变得无效。该对象仍然是可寻址的,您可以访问其数据和非虚方法,但尝试调用虚方法可能会崩溃。
在Windows系统上,DLL
可以与共享C运行时MSVRT.DLL
,或链接到" local" C运行时的副本(LIBCMT.LIB
等)。更多信息here。正如该页面所解释的那样,当使用静态链接的CRT
时,从它(包括堆)分配的资源是该DLL的本地资源。特别是,卸载此类DLL
将销毁从该DLL
堆分配的堆分配对象。