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实现中比较常见的问题,引以为戒。

目录
相关文章
|
2天前
|
存储 自然语言处理 安全
C++ STL标准库 《string原理与实战分析》
C++ STL标准库 《string原理与实战分析》
10 0
|
1天前
|
C++ 容器 存储
【C++语言】想学STL,先细细拿捏string类,万字详解string类 (内附精美思维导图)
【C++语言】想学STL,先细细拿捏string类,万字详解string类 (内附精美思维导图)
|
9天前
|
程序员 C++
C++初阶学习第七弹——探索STL奥秘(二)——string的模拟实现
C++初阶学习第七弹——探索STL奥秘(二)——string的模拟实现
15 1
|
9天前
|
C语言 C++
C++初阶学习第六弹——探索STL奥秘(一)——标准库中的string类
C++初阶学习第六弹——探索STL奥秘(一)——标准库中的string类
15 0
|
11天前
|
算法 Linux C语言
7.学习STL和string类:版本、组件、构造、操作及应用
7.学习STL和string类:版本、组件、构造、操作及应用
|
21天前
|
C++ 容器
黑马c++ STL部分 笔记(2) string容器
黑马c++ STL部分 笔记(2) string容器
|
28天前
|
存储 算法 搜索推荐
C++|STL简介-string-vector基础运用
C++|STL简介-string-vector基础运用
|
1天前
Failed to bind properties under ‘logging.level‘ to java.util.Map java.lang.String, java.lang.String
Failed to bind properties under ‘logging.level‘ to java.util.Map java.lang.String, java.lang.String
4 0
|
2天前
|
安全 Java 数据安全/隐私保护
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(二)
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(二)
12 0
|
2天前
|
JSON 安全 Java
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(一)
Java基础4-一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!(一)
8 0