在一些编译器中,STL中string采用了copy-on-write实现,这种情况会导致一些问题。
在我的工程中,首先是在Linux中编译项目,采用的是g++ 5.4,编译没有任何问题。当进行NDK的交叉编译的时候,由于NDK的toolchain中采用的是g++ 4.9,就出现了问题。问题的原因大概就是我在往一个string中写内容的时候,报访问非法内存的错误。这个string没有被显示的初始化,或者说采用的默认初始化。
这个问题的原因很奇怪,奇怪的地方在于一个用户进程声明的std::string为什么无法写入呢?查阅资料发现,g++ 4.9中std::string采用的copy-on-write实现,这就是问题所在了。
opy-on-write(以下简称COW)是一种很重要的优化手段。它的核心思想是懒惰处理多个实体的资源请求,在多个实体之间共享某些资源,直到有实体需要对资源进行修改时,才真正为该实体分配私有的资源。
COW技术的一个经典应用在于Linux内核在进程fork时对进程地址空间的处理。由于fork产生的子进程需要一份和父进程内容相同但完全独立的地址空间,一种做法是将父进程的地址空间完全复制一份,另一种做法是将父进程地址空间中的页面标记为共享的(引用计数+1),使子进程与父进程共享地址空间,但当有一方需要对内存中某个页面进行修改时,重新分配一个新的页面(拷贝原内容),并使修改进程的虚拟地址重定向到新的页面上。
COW技术有哪些优点呢?
COW的思想在资源管理上被广泛使用,甚至连STL中的std::string的实现也要沾一下边,g++ 4.9中实现的std::string便是COW的实现。
COW的核心思想就是lazy-copy。std::string的lazy-copy行为只发生在两个string对象之间的拷贝构造,赋值和assign操作上,如果一个string由(const)char*构造而来,则必然会分配内存和进行复制,因为string对象并不知道也无权控制char*所指内存的生命周期。
但是就是赋值导致了我的copy-on-write问题,由于在赋值之后,另一端的string被释放了,导致我这个string指向的内存是悬空的,因此写入的时候才会发生非法内存访问的错误。这也是copy-on-write实现中比较常见的问题,引以为戒。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。