如果我使用malloc()
分配一些内存,有没有办法将其标记为只读。所以如果有人试图写入它,memcpy(( 会失败?
这与错误的 api 设计有关,其中用户错误地使用了由方法返回的 const 指针GetValue()
该方法是大内存结构的一部分。由于我们希望避免复制大块内存,因此我们在具有特定格式的结构化内存中返回实时指针。现在的问题是,一些用户通过直接写入此内存并避免执行分配并正确处理我们开发的内存二进制格式的 SetValue(( 调用来找到工作的方法。虽然有时有黑客工作,但有时它会导致内存访问冲突,因为控制标志的错误解释已被用户覆盖。
教育用户是一项任务,但现在让我们说我们希望代码失败。
我只是想知道我们是否可以简单地防止这种情况。
为了类比,假设有人从 sqlite 语句中获取一个 blob 列,然后写回它。虽然在 sqlite 的情况下它没有意义,但这在我们的情况下有点令人高兴。
在大多数硬件体系结构上,您只能更改整个内存页上的保护属性;不能将页面片段标记为只读。
相关的 API 包括:
- 在 Unix 上
mprotect()
; -
VirtualProtect()
在Windows上。
您需要确保内存页不包含您不想设为只读的任何内容。为此,您必须使用 malloc()
过度分配,或使用不同的分配 API,例如 mmap()
、posix_memalign()
或 VirtualAlloc()
。
取决于平台。在 Linux 上,你可以使用 mprotect(( (http://linux.die.net/man/2/mprotect(。
在Windows上,你可以尝试VirtualProtect(((http://msdn.microsoft.com/en-us/library/windows/desktop/aa366898(v=vs.85(.aspx(。不过我从来没有用过它。
编辑:这不是NPE答案的重复。NPE最初有不同的答案;它后来被编辑,并添加了mprotect((和VirtualProtect((。
一个错误的 API 设计,用户错误地使用了由方法 GetValue(( 返回的常量指针,该方法是大内存结构的一部分。由于我们希望避免复制大块内存,因此我们在具有特定格式的结构化内存中返回实时指针
这显然不是一个错误的 API 设计。API 是一个契约:你承诺你的类将以特定的方式运行,类的客户端承诺以正确的方式使用 API。像const_cast
这样的肮脏伎俩是不恰当的(在某些情况下,但并非所有情况下,都有未定义的行为(。
如果使用const_cast
会导致安全问题,那将是错误的 API 设计。在这种情况下,您必须复制内存块,或重新设计 API。这是Java中的规范,Java没有等同于const
(尽管const
在Java中是一个保留字(。
混淆指针,即将指针加上偏移量返回给客户端,现在他们不能直接使用指针。每当指针通过官方 API 传递到您的代码时,请减去偏移量并像往常一样使用指针。