为啥没有用零填充

Posted

技术标签:

【中文标题】为啥没有用零填充【英文标题】:why did not fill with zeros为什么没有用零填充 【发布时间】:2017-01-18 22:39:04 【问题描述】:

为 10000 位分配的数组 = 1250 字节(10000/8):

mov edi, 1250
call malloc

测试过指针:

cmp rax, 0
jz .error ; error handling at label down the code

内存已分配:

(gdb) p/x $rax
$3 = 0x6030c0

尝试用零填充分配的内存:

mov rdi, rax
xor esi, esi
mov edx, 1250 ; 10000 bits
call memset

检查第一个字节:

(gdb) p/x $rax
$2 = 0x6030c0
(gdb) x/xg $rax + 0
0x6030c0: 0x0000000000000000

检查最后一个字节(0 - 第一个字节,1249 - 最后一个字节)

(gdb) p/x $rax + 1249
$3 = 0x6035a1
(gdb) x/xg $rax + 1249
0x6035a1: 0x6100000000000000

已解决的问题 应该输入x/1c $rax + 1249

【问题讨论】:

最后一个字节为零:0x6100000000000000。当您读取 8 字节值时,您会在最后一个字节之后获得 7 个字节,并且您不需要将它们归零。 我正在使用带有小端序的 intel x64(i3)。所以看起来最重要的字节(0x61)应该在缓冲区的最后?或者我犯了错误,请纠正。 您需要使用$rax + 1242 来读取缓冲区的最后 8 个字节。现在您只读取缓冲区的最后一个字节加上缓冲区后的 7 个字节。这 7 个字节不需要为零。 Little-endian 表示最低有效字节在前(地址较小):0x($rax + 1256)61($rax +1255)00($rax +1254)00($rax +1253 )00($rax +1252)00($rax +1251)00($rax +1250)00($rax +1249)00. 现在我明白了,命令应该是x/1c $rax + 1249,并且会准确显示最后一个字节。 【参考方案1】:

您将内存解释为 64 位整数,但您忘记了 intel 的字节序是小字节序。所以字节被颠倒了。

0x6100000000000000是CPU在反序列化该地址的内存时读取的值。由于是小端,0x61 字节在内存中是最后一个(以这种格式转储内存不是很方便,除非你有大端架构)

使用x /10bx $rax + 1249,您会看到它在正确的位置为零。剩下的都是垃圾(碰巧一会为零,然后是垃圾)

0x00    0x00    0x00    0x00    0x00    0x00    0x61

【讨论】:

我得到0x6035a1: 0 '\000' 0 '\000' 0 '\000' '\000' 0 '\'000' 0 '\'000' 0 '\'000' 97 'a',很奇怪 此调试格式发出值 + 字符表示。所以这是正常的。使用这种格式,您可以获得内存中的内容,而不是 CPU 在将数据加载到整数寄存器时所解释的内容。

以上是关于为啥没有用零填充的主要内容,如果未能解决你的问题,请参考以下文章

为啥 toLocaleTimeString(),总是零填充分钟和秒

为啥我的 CUDA 代码无法正常工作以零填充大型矩阵?

为啥我在使用 memset 用零填充对象后在 dynamic_cast 出现异常

为啥 InputStream 没有完全填充数组?

如何用前导零填充数组?

用 MySQL 数据填充 Datagridview