什么是C++03中用于并发的内存模型?
(而且,C++11是否改变了内存模型以更好地支持并发?)
什么是C++03中用于并发的内存模型?
(而且,C++11是否改变了内存模型以更好地支持并发?)
C++内存模型规定了物理内存何时以及为什么会被读写。
在下一个C++标准之前,C++的内存模型与C相同。在C++0x标准中,预计将包括适用于多线程的正确的内存模型(请参见这里),并且它可能是下一版C标准C1X的一部分。当前标准非常简陋:
所以当前的状态是:只有在您有一个进程及其主线程并且不编写依赖于变量读/写的特定顺序的代码时,才指定C++内存操作。实质上,这意味着除了传统的hello world程序之外,您的程序可能会遇到困难。
当然,您可能会很快地添加"在我的机器上运行良好,您不可能是对的"。正确的句子应该是"使用特定的硬件组合、操作系统(线程库)和编译器,在我的机器上运行良好,并且彼此了解足以实现某些工作,但很可能会在某个时候出现问题"。
好吧,这有点苛刻,但是看看Herb Sutter所承认的(只需阅读介绍部分),他谈论的是最广泛使用的C/C++工具链的所有2007年之前的版本...
C++标准委员会试图设计出一种能够解决这些问题的方案,同时比Java的内存模型更加灵活(从而性能更好)。
Hans Boehm在这里收集了一些与此问题相关的论文和来自C++委员会的资料。
看了一些其他回答,似乎许多C++程序员甚至不知道你所问的"内存模型"是什么意思。
这个问题涉及内存模型的意义:关于写入/读取重排序(可能发生在编译器或运行时),有什么保证(如果有)?此问题对于多线程编程非常重要,因为没有这样的规则,编写正确的多线程程序是不可能的,而令人惊讶的事实是,在当前缺乏显式内存模型的情况下,许多多线程程序基本上都是通过“纯属运气”工作的-往往要感谢编译器假定函数调用间的指针别名。 -请参见Threads Cannot be Implemented as a Library
在当前的C ++中,没有标准的内存模型。一些编译器为volatile变量定义了内存模型,但这是非标准的。 C ++0x定义了新的“原子”原语来实现此目的。检查最近状态的详尽起点可在Threads and memory model for C ++找到
重要链接也包括并发内存模型,原子类型和C ++数据依赖性排序:原子和内存模型标准提案。
很遗憾,C++中没有像Java那样的“标准内存模型”。实际实现由编译器、运行时库和处理器决定。
因此,C++内存模型等同于混合杂糅的模型,这意味着您始终需要尝试编写安全代码,不依赖于特定的内存模型。对于线程编程也是如此,因为编译器可以在关键部分之外进行任何优化,甚至乱序处理!
简短回答:没有
长篇回答:C++没有托管内存,您必须自己分配和释放内存。智能指针类可以使这个过程更轻松。如果您忘记释放已分配的内存,那就是内存泄漏和错误。如果您尝试在释放内存后使用内存,或者尝试多次释放内存,那也是非常严重的错误。
至于底层细节,C++没有规定 - 这取决于硬件。内存通过指针访问,其中包含某种内存地址。内存地址可以是物理地址或虚拟地址。只有在操作系统内核上工作或读取在实模式下运行的旧DOS代码时,您才会看到物理地址。有关更多详细信息,请阅读虚拟内存,有很多好的资源可供参考。
x86架构还允许使用段描述符来寻址内存。这是一个完全不同的问题,自Win16以来就没有真正被使用过了,如果您幸运的话,您永远不需要处理它。
一个向下增长的堆栈--也就是说,当你推入一个堆栈帧时,堆栈指针的值比它之前的值小
一个向上增长的堆,也就是新分配的内存的结束地址比之前的内存大。你可以使用malloc()或new在堆中分配内存。如果堆中没有足够的内存可用,则malloc(或new)调用系统函数brk() sbrk()来增加堆的大小。如果调用brk()或sbrk()失败,则malloc或new会因为内存不足而失败。
你永远不需要关心堆栈或堆是否向下或向上增长,在某些系统中,它们可能以相反的方式运行。只需考虑堆栈和堆从地址空间的末端向内增长即可。
一个内存分配器malloc,它按8位字节分配内存。New也分配内存,但它分配的内存量基于被newed对象的大小。
文本空间,其中包含可执行代码。文本位于堆下方。你不能在执行期间更改文本空间。
一个程序可能有其他特殊用途的文本部分。
您可以使用Linux系统上的objdump查看程序在静态(加载之前)时的组织方式。
我注意到,尽管您在问题中没有提到它,“并发性”是您分配给此问题的关键字之一。线程系统为每个线程在堆上分配额外的线程空间,然后管理堆栈指针以在线程之间切换。
还有很多细节,其中许多是特定于特定硬件、操作系统或线程系统的,但这是基本思想。