将二进制文件复制到 c 中的缓冲区的正确方法

correct way to copy binary file to buffer in c

我正在尝试打开一个 bin 文件并将其数据放入缓冲区并将数据从该缓冲区复制到我创建的名为 .my_data 的部分。 当我做 hexdump binfile.bin 我看到

   00000000 4455 e589 00bf 0000 e800 0000 00b8
   00000010 5d00 00c3
   00000015

当我打印 buffer 和 buffer2 时,我看到了

   55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00 00 00 00 5d c3 

   55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00 00 00 00 5d c3

这与 hexdump 的输出匹配。但是,当将 buffer2 加载到我的新部分(我没有包含那部分代码)时,我使用了 objdump -s -j .my_data foo 并且我看到了一些与上面的输出不相似的其他数据。

对于这个愚蠢的问题,我深表歉意,但我只想确认我使用的 memcpy 是否真的将数据从 buffer 复制到 buffer2,这样我就可以放弃这部分并在我的程序的其余部分查找错误。从第二个 for 循环的输出来看,我认为是。我也在用 gcc,谢谢。

   #include <stdio.h>
   #include <stdint.h>
   #include <string.h>
   #include <stdlib.h>
   
   int main (){

   uint8_t buffer[21];
   uint8_t buffer2[21];
   FILE *ptr;
   ptr = fopen("binfile.bin", "rb");
   size_t file_size = 0;
   
   if(!ptr)
   {
     printf("unable to open file");
     return 1;
   }

   fseek(ptr, 0, SEEK_END);
   file_size = ftell(ptr); 
   rewind(ptr);

   int i = 0;
   
   fread(buffer, sizeof(buffer), 1, ptr);
   memcpy(buffer2, buffer, sizeof(buffer));

   for(i = 0; i < 21; i++)
   {
    printf("%02x ", buffer[i]);
   }

   printf("\n\n");
   for(i = 0; i < 21; i++)
   {
    printf("%02x ", buffer2[i]);
   }

   fclose(ptr);
  
   return 0;

   }

    

这里是更正后的代码:打印时注意 & 0xFF

uint8_t buffer[21];
uint8_t buffer2[21];
FILE *ptr;
ptr = fopen("binfile.bin", "rb");
size_t file_size = 0;

if (!ptr)
{
    printf("unable to open file");
    return 1;
}

fseek(ptr, 0, SEEK_END);
file_size = ftell(ptr);
rewind(ptr);

int i = 0;

fread(buffer, sizeof(buffer), 1, ptr);
memcpy(buffer2, buffer, sizeof(buffer));

for (i = 0; i < sizeof buffer; i++)
{
    printf("%02x ", buffer[i] & 0xFF);
}

printf("\n\n");
for (i = 0; i < sizeof buffer2; i++)
{
    printf("%02x ", buffer2[i] & 0xFF);
}

fclose(ptr);

return 0;

这是输出

55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00 00 00 00 5d c3

55 48 89 e5 bf 00 00 00 00 e8 00 00 00 00 b8 00 00 00 00 5d c3

就如何将 buffer 复制到 buffer2 而言,您的想法是正确的,但您未能确保仅尝试访问 buffer 的元素有效初始化。由于您的文件仅包含 20 字节,因此当您尝试访问 buffer[20] 时,您正在尝试访问具有 自动存储持续时间 而值为 [=39] 的变量=]不确定调用未定义的行为。所有投注均已取消。

您可以通过完全初始化 buffer 来处理这个问题,例如

uint8_t buffer[21] = {0);

如果用 fread 填充少于所有元素仍然可以,因为所有元素都已有效初始化。

另一种方法是简单地使用 size 参数读取 fread 设置为 1 所以 fread returns 读取的字节数。然后您可以使用该值来输出结果,例如

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXC 1024       /* max number of characters (bytes) */

int main (int argc, char **argv) {
    
    size_t nbytes = 0;
    unsigned char buf1[MAXC] = {0}, buf2[MAXC] = {0};
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;
    
    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }
    
    nbytes = fread (buf1, 1, MAXC, fp);     /* with size=1, no. of bytes returned */
    
    if (fp != stdin)                        /* close file if not stdin */
        fclose (fp);
    
    memcpy (buf2, buf1, nbytes);            /* copy nbytes buf1, buf2 */
    
    for (size_t i = 0; i < nbytes; i++)     /* outuput buf1 contents */
        printf (" %02x", buf1[i]);
    putchar ('\n');

    for (size_t i = 0; i < nbytes; i++)     /* output buf2 contents */
        printf (" %02x", buf2[i]);
    putchar ('\n');
}

例子Use/Output

根据文件 dat/bytes20.bin 中的数据,您将收到:

$ ./bin/fread_bytes dat/bytes20.bin
 44 55 e5 89 00 bf 00 00 e8 00 00 00 00 b8 5d 00 00 c3
 44 55 e5 89 00 bf 00 00 e8 00 00 00 00 b8 5d 00 00 c3

如果您还有其他问题,请告诉我。