STL中string的copy-on-write实现导致的问题

简介: STL中string的copy-on-write实现导致的问题

在一些编译器中,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实现,这就是问题所在了。


copy-on-write


opy-on-write(以下简称COW)是一种很重要的优化手段。它的核心思想是懒惰处理多个实体的资源请求,在多个实体之间共享某些资源,直到有实体需要对资源进行修改时,才真正为该实体分配私有的资源。

COW技术的一个经典应用在于Linux内核在进程fork时对进程地址空间的处理。由于fork产生的子进程需要一份和父进程内容相同但完全独立的地址空间,一种做法是将父进程的地址空间完全复制一份,另一种做法是将父进程地址空间中的页面标记为共享的(引用计数+1),使子进程与父进程共享地址空间,但当有一方需要对内存中某个页面进行修改时,重新分配一个新的页面(拷贝原内容),并使修改进程的虚拟地址重定向到新的页面上。

COW技术有哪些优点呢?

  1. 减少了分配(和复制)大量资源带来的瞬间延迟(注意仅仅是latency,但实际上该延迟被分摊到后续的操作中,其累积耗时很可能比一次统一处理的延迟要高,造成throughput下降是有可能的)
  2. 另一方面减少不必要的资源分配。(例如在fork的例子中,并不是所有的页面都需要复制,比如父进程的代码段(.code)和只读数据(.rodata)段,由于不允许修改,根本就无需复制。而如果fork后面紧跟exec的话,之前的地址空间都会废弃,花大力气的分配和复制只是徒劳无功。)
  3. 数据一致性:COW技术通过在写入操作时创建新的副本,确保了数据的一致性。因为每个进程或线程都拥有自己的副本,在进行修改时不会影响其他进程的数据。这样可以避免并发访问导致的数据不一致性问题。

COW的思想在资源管理上被广泛使用,甚至连STL中的std::string的实现也要沾一下边,g++ 4.9中实现的std::string便是COW的实现。


COW导致的问题


COW的核心思想就是lazy-copystd::string的lazy-copy行为只发生在两个string对象之间的拷贝构造赋值assign操作上,如果一个string由(const)char*构造而来,则必然会分配内存和进行复制,因为string对象并不知道也无权控制char*所指内存的生命周期。

但是就是赋值导致了我的copy-on-write问题,由于在赋值之后,另一端的string被释放了,导致我这个string指向的内存是悬空的,因此写入的时候才会发生非法内存访问的错误。这也是copy-on-write实现中比较常见的问题,引以为戒。

目录
相关文章
|
3月前
|
存储 自然语言处理 安全
C++ STL标准库 《string原理与实战分析》
C++ STL标准库 《string原理与实战分析》
60 0
|
1月前
|
存储 算法 程序员
【STL】string
【STL】string
|
3月前
|
安全 算法 C语言
【C++进阶】深入STL之string:掌握高效字符串处理的关键
【C++进阶】深入STL之string:掌握高效字符串处理的关键
40 1
【C++进阶】深入STL之string:掌握高效字符串处理的关键
|
3月前
|
编译器 C++
【C++进阶】深入STL之string:模拟实现走进C++字符串的世界
【C++进阶】深入STL之string:模拟实现走进C++字符串的世界
33 1
|
3月前
|
编译器 C语言 C++
【C++/STL】:string类底层的模拟实现
【C++/STL】:string类底层的模拟实现
29 0
|
3月前
|
算法 C++ 容器
【C++/STL】:string类的基本使用
【C++/STL】:string类的基本使用
21 0
|
3月前
|
C++ 容器 存储
【C++语言】想学STL,先细细拿捏string类,万字详解string类 (内附精美思维导图)
【C++语言】想学STL,先细细拿捏string类,万字详解string类 (内附精美思维导图)
|
29天前
|
API 索引
String类下常用API
String类下常用API
32 1
|
29天前
for循环和String类下方法的一个练习题
for循环和String类下方法的一个练习题
42 1
|
5天前
|
存储 安全 Java
Java——String类详解
String 是 Java 中的一个类,用于表示字符串,属于引用数据类型。字符串可以通过多种方式定义,如直接赋值、创建对象、传入 char 或 byte 类型数组。直接赋值会将字符串存储在串池中,复用相同的字符串以节省内存。String 类提供了丰富的方法,如比较(equals() 和 compareTo())、查找(charAt() 和 indexOf())、转换(valueOf() 和 format())、拆分(split())和截取(substring())。此外,还介绍了 StringBuilder 和 StringJoiner 类,前者用于高效拼接字符串,后者用于按指定格式拼接字符串
11 1
Java——String类详解