尝试解析 WAV 文件,memcpy 结果出乎意料
Attempting to parse a WAV file, memcpy results are unexpected
假设我有一个小的 WAV 文件,我打开并转储为 char
的数组以供处理。
现在,我正在尝试将 memcpy
fmt
块 ID 放入 4 字节缓冲区。
char fmt[4];
memcpy(fmt_chunk_id, raw_file + 12, sizeof(char) * 4);
根据我对memcpy
的理解,这会将从偏移量 12 开始的 4 个字节复制到 fmt
。但是,当我去调试程序时,我得到了一些非常奇怪的输出:
似乎正确复制了 fmt
部分,但现在由于某种原因我在它后面有一堆垃圾。有趣的是,此垃圾在偏移字节 0 (RIFF
) 和 8 (WAVE
) 处以 before 格式出现。这是一个小端文件 (RIFF
).
我这辈子都想不通为什么我要从 结束 [=47= 缓冲区的 开始 处获取数据] 考虑到我只复制了 4 个字节的数据(这应该正好适合前 4 个字符 f
m
t
和 space)。
这是怎么回事?输出似乎向我表明我在某处过度读取内存 - 但如果是这种情况,我会期待垃圾而不是以前的偏移量数据。
编辑:
如果重要的话,raw_file
的数据类型是const char* const
。
调试器正在向您显示在堆栈上动态分配的内存区域。
很可能发生的情况是您从文件中读取数据,即使您要求读取 50 字节,底层系统也可能决定读取更多(1024、2048 或 4096 字节)通常)。所以那些字节在内存中传递,可能一些在堆栈中,并且该堆栈现在正被您的函数重用。如果您要求读取超过这四个字节,则更有可能发生这种情况。
然后调试器看到您指向一个字符串,但在 C 字符串中 运行 直到它们被零 (ASCIIZ) 终止。所以你看到的是前四个字节 和后面的所有其他内容,直到第一个 0x00 字节 .
如果这对你很重要,就
char fmt[5];
fmt[4] = 0;
// read four bytes into fmt.
现在调试器只会显示前四个字节。
但现在您明白了为什么在释放内存区域之前始终清除和覆盖内存区域中的敏感信息()——数据可能会保留在那里,甚至会被意外重复使用或丢弃。
假设我有一个小的 WAV 文件,我打开并转储为 char
的数组以供处理。
现在,我正在尝试将 memcpy
fmt
块 ID 放入 4 字节缓冲区。
char fmt[4];
memcpy(fmt_chunk_id, raw_file + 12, sizeof(char) * 4);
根据我对memcpy
的理解,这会将从偏移量 12 开始的 4 个字节复制到 fmt
。但是,当我去调试程序时,我得到了一些非常奇怪的输出:
似乎正确复制了 fmt
部分,但现在由于某种原因我在它后面有一堆垃圾。有趣的是,此垃圾在偏移字节 0 (RIFF
) 和 8 (WAVE
) 处以 before 格式出现。这是一个小端文件 (RIFF
).
我这辈子都想不通为什么我要从 结束 [=47= 缓冲区的 开始 处获取数据] 考虑到我只复制了 4 个字节的数据(这应该正好适合前 4 个字符 f
m
t
和 space)。
这是怎么回事?输出似乎向我表明我在某处过度读取内存 - 但如果是这种情况,我会期待垃圾而不是以前的偏移量数据。
编辑:
如果重要的话,raw_file
的数据类型是const char* const
。
调试器正在向您显示在堆栈上动态分配的内存区域。
很可能发生的情况是您从文件中读取数据,即使您要求读取 50 字节,底层系统也可能决定读取更多(1024、2048 或 4096 字节)通常)。所以那些字节在内存中传递,可能一些在堆栈中,并且该堆栈现在正被您的函数重用。如果您要求读取超过这四个字节,则更有可能发生这种情况。
然后调试器看到您指向一个字符串,但在 C 字符串中 运行 直到它们被零 (ASCIIZ) 终止。所以你看到的是前四个字节 和后面的所有其他内容,直到第一个 0x00 字节 .
如果这对你很重要,就
char fmt[5];
fmt[4] = 0;
// read four bytes into fmt.
现在调试器只会显示前四个字节。
但现在您明白了为什么在释放内存区域之前始终清除和覆盖内存区域中的敏感信息()——数据可能会保留在那里,甚至会被意外重复使用或丢弃。