如何制作一个空指针来读取二进制文件的给定部分

How to make a void pointer to read a given part of a binary file

我有一个二进制文件,其中包含 3 个不同的结构和一个圣诞节文本。在二进制文件的第一行,他们为我提供了一个代表文件内包大小的整数。一个包包含 3 个结构,chistmastext 和大小。 这些结构位于一个名为 framehdr.h 的文件中,我正在阅读的二进制文件名为 TCPdump。

现在我正在尝试创建一个程序,att 将一次读取每个包,然后撤回文本。 我从这样的事情开始:

#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include "framehdr.h"
#include <crtdbg.h>

int main()
{
  _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  FILE *fileOpen;
  char *buffer;
  size_t dataInFile;
  long filesize;

  // The three structs
  struct ethernet_hdr ethHdr;
  struct ip_hdr ipHdr;
  struct tcp_hdr tcpHDr;

  fileOpen = fopen("C:\Users\Viktor\source\repos\Laboration_3\Laboration_3\TCPdump", "rb");
  if (fileOpen == NULL)
  {
    printf("Error\n");
  }
  else
  {
    printf("Success\n");
  }

  char lenOf[10];
  size_t nr;
  // Reads until \n comes 
  fgets(lenOf, sizeof(lenOf), fileOpen);
  sscanf(lenOf, "%d", &nr);
  // Withdraw the size of a package and check if it's correct
  printf("Value: %d\n", nr);
  printf("Adress: %d\n", &nr);

  void *ptr;
  fread(&ptr, nr, 1, fileOpen);
  int resEth = 14;
  printf("resEth: %d\n", resEth);
  int resIP = IP_HL((struct ip_hdr*)ptr);
  printf("ResIP: %d\n", resIP);
  int resTcp = TH_OFF((struct tcp_hdr*)ptr);
  printf("tcpIP: %d\n", resTcp);
  int res = resEth + resIP + resTcp;
  printf("Total: %d", res);

  fclose(fileOpen);
  //free(buffer);

  system("pause");

  return 0;
}

我知道第一个 struct ethernet 的大小始终为 14,但我需要获取其他 2 个的大小,我想为此使用 IP_HL 和 TH_OFF .

但我的问题在于我似乎无法将整个包读成一个 void * 与恐惧。我在我的 *ptr 中注意到了。 当我尝试将 void * 转换为其中一个结构时,这又会导致代码中断。

void * 我做错了什么?

两个问题:

首先你不应该在读取二进制文件时真正使用文本函数。二进制文件实际上并没有 "lines",因为文本文件有它。

其次,与

void *ptr;
fread(&ptr, nr, 1, fileOpen);

您正在将指针 传递给指针变量 ,您实际上并没有将任何内容读入内存,然后使 ptr 指向该内存。现在发生的是fread函数会从文件中读取nr字节,然后写入到&ptr指向的内存中,这会导致undefined behavior if nr > sizeof ptr(因为那时数据将被写出边界)。

您必须分配 nr 字节的内存,然后将指针传递给该内存的第一个元素:

char data[nr];
fread(data, nr, 1, fileOpen);

您还应该养成检查错误的习惯。如果 fread 函数失败怎么办?或者文件被截断,没有 nr 个字节可供读取?

您可以通过检查 fread returns.

来检查这些条件

并且不仅检查 fread,还有比 fopen 更多的功能可能会失败。