注意:如果在读完这个问题后您认为“这怎么可能发生”,那没关系。如果您想保持开放的心态,您可以遵循问题后的一些要点,这些要点说明了这是如何发生的以及为什么这样做有用。请记住,这只是一个问题,而不是关于这些主题的教程。这些评论已经有足够的噪音,而且很难跟上。如果您对这些主题有疑问,请将它们作为问题发布在 SO 而不是评论中,我将不胜感激。
问题:如果我有一个 int 类型的对象存储在 c
int* c = /* allocate int (returns unique address) */;
*c = 3;
由两个指针 a 和 b 引用:
int* a = /* create pointer to (*c) */;
int* b = /* create pointer to (*c) */;
这样:
assert(a != b); // the pointers point to a different address
assert(*b == 3);
*a = 2;
assert(*b == 2); // but they refer to the same value
这是未定义的行为吗?如果是,C++ 标准的哪一部分不允许这样做?如果不允许,C++ 标准的哪些部分允许这样做?
注意:c指向的内存是通过返回唯一地址的内存分配函数分配的(new, malloc ,...)。创建具有不同值的这些指针的方法是非常特定于平台的,尽管在大多数 unix 系统中可以使用 mmap 完成,而在 Windows 上可以使用 VirtualAlloc 完成。
背景:大多数操作系统(那些拥有不在环 0 上的用户空间的操作系统)在虚拟内存上运行它们的进程,并且具有从虚拟内存页到物理内存页的映射。其中一些系统(Linux/MacOS/BSDs/Unixes 和 64 位 Windows)提供了一些可用于映射两个虚拟内存页的系统调用(如 mmap 或 VirtualAlloc)到同一个物理内存页。当进程执行此操作时,它实际上可以从两个不同的虚拟内存地址访问同一页物理内存。也就是说,这两个指针将具有不同的值,但它们将访问相同的物理内存存储。 google 的关键字:mmap、虚拟内存、内存页面。使用此功能获利的数据结构是“魔术环形缓冲区”(这是技术术语)和非重新分配动态大小的 vector (即,当它们增长时不需要重新分配内存的 vector )。 Google 提供的有关这些的信息比我在这里所能提供的更多。
非常小的可能无法工作的示例(仅限 unix):
我们首先在堆上分配一个int。以下请求一个匿名的、非文件支持的虚拟内存映射。这里必须至少请求一个完整的内存页,但为了简单起见,我只请求 int 的大小(mmap 无论如何都会分配一个完整的内存页):
int* c= mmap(NULL, sizeof(int), PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE,-1, 0);
现在我们需要将它映射到两个独立的内存位置,所以我们将它映射到同一个内存映射文件,两次,例如,两个相邻的内存位置。我们不会真正使用这个文件,但我们仍然需要创建它并打开它:
mmap(c, sizeof(int), PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, some_fd, 0);
mmap(c + 1, sizeof(int), PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, some_fd, 0);
现在我们快完成了:
int* a = c;
int* b = c + 1;
这些显然是不同的虚拟地址:
assert(a != b);
但它们指向相同的、非文件支持的物理内存页:
*a = 314;
assert(*b == 314);
就这样吧。使用 VirtualAlloc 可以在 Windows 上完成相同的操作,但 API 有点不同。
最佳答案
首先让我们看看标准对对象的看法
[intro.object]
The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. —end note ] An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed. The properties of an object are determined when the object is created. An object can have a name (Clause 3). An object has a storage duration (3.7) which influences its lifetime (3.8). An object has a type (3.9). The term object type refers to the type with which the object is created. Some objects are polymorphic (10.3); the implementation generates information associated with each such object that makes it possible to determine that object’s type during program execution. For other objects, the interpretation of the values found therein is determined by the type of the expressions (Clause 5) used to access them.
然后我们有
Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects that are not bit-fields may have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses.
所以我们知道一个对象有一个地址,它是它使用的存储空间的第一个字节。如果我们看看我们有什么字节
[intro.memory]
The fundamental storage unit in the C++ memory model is the byte. A byte is at least large enough to contain any member of the basic execution character set (2.3) and the eight-bit code units of the Unicode UTF-8 encoding form and is composed of a contiguous sequence of bits, the number of which is implementationdefined. The least significant bit is called the low-order bit; the most significant bit is called the high-order bit. The memory available to a C++ program consists of one or more sequences of contiguous bytes. Every byte has a unique address.
强调我的
因此,如果我们有一个指向对象的指针,该指针将保存一个唯一值(地址)。如果我们有另一个指向同一个对象的指针,那么它也必须具有相同的值(地址)。未定义的行为甚至不会进入等式,因为您根本无法让两个指针指向具有不同值的同一对象。
关于c++ - 有两个具有不同值的指针引用同一个对象是未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35852493/
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象