Akt*_*tau 6 c macos assembly memory-management libc
在研究OSX 10.9.4的strlen实现时,我注意到它总是比较一个16字节的块并向前跳过到接下来的16个字节,直到它遇到'\0''.相关部分:
3de0: 48 83 c7 10 add $0x10,%rdi
3de4: 66 0f ef c0 pxor %xmm0,%xmm0
3de8: 66 0f 74 07 pcmpeqb (%rdi),%xmm0
3dec: 66 0f d7 f0 pmovmskb %xmm0,%esi
3df0: 85 f6 test %esi,%esi
3df2: 74 ec je 3de0 <__platform_strlen+0x40>
Run Code Online (Sandbox Code Playgroud)
0x10 十六进制是16个字节.
当我看到它时,我想知道:这个记忆也可以不被分配.如果我已经分配了一个20字节的C字符串并将其传递给strlen它,它将读取36字节的内存.为什么允许这样做?我开始寻找并发现访问数组越界有多危险?
例如,这证实了它绝对不是一件好事,未分配的内存可能未被映射.然而,必须有一些东西使这项工作.我的一些假设:
究竟是什么原因?
编辑:刚刚找到为什么我获得了未分配内存的读写权限?,这似乎表明我的第一个猜测是正确的.
编辑2:愚蠢的是,我已经忘记了尽管Apple似乎已经删除了大多数asm实现的源代码(OSX的x86-64汇编libc例程在哪里?),但是它留下了strlen:http://www.opensource .apple.com /源极/ libc的/ libc的-997.90.3/x86_64的/串/ strlen.s
在评论中我们发现:
// returns the length of the string s (i.e. the distance in bytes from
// s to the first NUL byte following s). We look for NUL bytes using
// pcmpeqb on 16-byte aligned blocks. Although this may read past the
// end of the string, because all access is aligned, it will never
// read past the end of the string across a page boundary, or even
// accross a cacheline.
Run Code Online (Sandbox Code Playgroud)
编辑:老实说,我认为所有的答案者都应该得到一个可接受的答案,而且基本上都包含了解问题所需的信息.所以我找到了声誉最低的人的答案.
我是这个例程的作者.
正如其他人所说,关键是读取都是一致的.虽然在数组的边界外读取是C中未定义的行为,但我们不是在写C; 除了C抽象机器定义的内容之外,我们知道x86架构的许多细节.
特别是,超出缓冲区末尾的读取是安全的(意味着它们不能产生陷阱或其他可观察的副作用),只要它们不跨越页面边界(因为以页面粒度跟踪内存属性和映射).由于支持的最小页面大小为4096字节,因此对齐的16字节加载不能跨越页边界.
如果正在读取的地址对应于未映射的页面,则在大多数架构上读取内存只会产生副作用。现代计算机的大多数strlen实现都尝试只对任意数量的字节进行对齐读取。它们永远不会跨两个页面进行 16 字节读取,因此它们永远不会引起任何副作用。所以这很酷。
| 归档时间: |
|
| 查看次数: |
461 次 |
| 最近记录: |