Очередь C, неправильно хранящая значения

#c #queue

#c #очередь

Вопрос:

Я пытаюсь настроить очередь на C, но когда что-то новое ставится в очередь, оно каждый раз дублирует значение head вместо сохранения этого нового элемента.

 
#include <pcap.h>
#include <pthread.h>
#include <stdlib.h>

struct packet_queue {
  struct pcap_pkthdr *header;
  unsigned char *packet;
  struct packet_queue *next;
};
struct packet_queue *head = NULL;
struct packet_queue *tail = NULL;

int run = 0;
int packets = 0;
int v;


void enqueue(struct packet_queue *pq) {
  if (head == NULL) {
    head = pq;
  }
  else {
    struct packet_queue *current = head;
    while (current->next != NULL) {
      current = current->next;
    }
    current->next = pq;
  }
  packets  ;
}


void printqueue() {
  struct packet_queue * current = head;
  int i = 50;
  while (i > 0 amp;amp; current != NULL) {
    printf("%dn", current->header->len);
    current = current->next;
    i--;
  }
}

void dispatch(struct pcap_pkthdr *header,
              const unsigned char *packet,
              int verbose) {
  v = verbose;
  int i;

  struct packet_queue *next_packet = (struct packet_queue *) malloc(sizeof(struct packet_queue));
  next_packet->header = (struct pcap_pkthdr *) header;
  next_packet->packet = (unsigned char * ) packet;
  next_packet->next = NULL;
  enqueue(next_packet);
}
  

При печати очереди printqueue() с ее использованием каждый раз выводится одно и то же значение (значение заголовка), предполагающее, что заголовок дублируется в очереди.

РЕДАКТИРОВАТЬ: провел еще немного тестирования и понял, что вся очередь настроена на то, что является последним добавленным элементом.

 struct pcap_pkthdr header;
  const unsigned char *packet;

  //initialise dynamic array
  dynarray_init(amp;syn_adds, 5);

  while (1) {
    // Capture a  packet
    packet = pcap_next(pcap_handle, amp;header);
    if (packet == NULL) {
      // pcap_next can return null if no packet is seen within a timeout
      if (verbose) {
        printf("No packet received. %sn", pcap_geterr(pcap_handle));
      }
    } else {
      // Optional: dump raw data to terminal
      if (verbose) {
         //dump(packet, header.len);
      }
      // Dispatch packet for processing
      dispatch(amp;header, packet, verbose);
    }
  }
}
  

Комментарии:

1. Не связано с рассматриваемой проблемой, но преобразование a const unsigned char * в an unsigned char * не является хорошей идеей.

2. Что вызывает dispatch ? Где находятся header и packet выделяются?

3. @JosephSible-Переустановите Monica Я добавил const в структуру спасибо! Я отредактировал вопрос, чтобы добавить, где вызывается отправка

4. «Структура pcap_pkthdr и пакетные данные не должны освобождаться вызывающим объектом и не гарантируется, что они будут действительными после следующего вызова pcap_next_ex(), pcap_next(), pcap_loop() или pcap_dispatch(); если код нуждается в том, чтобы они оставались действительными, он должен сделать копиюиз них. » manpages.ubuntu.com/manpages/xenial/man3 /…

Ответ №1:

Ваша очередь в порядке. Проблема в том, что вы вызываете dispatch с теми же указателями. Вы продолжаете передавать адрес того же struct pcap_pkthdr header; , header что и, и в руководстве для pcap_next этого сказано:

pcap_next() считывает следующий пакет (вызывая pcap_dispatch() с cnt равным 1) и возвращает указатель u_char на данные в этом пакете. Данные пакета не должны освобождаться вызывающим объектом и не гарантируется, что они будут действительными после следующего вызова pcap_next_ex(), pcap_next(), pcap_loop() или pcap_dispatch(); если коду необходимо, чтобы они оставались действительными, он должен сделать их копию. Структура pcap_pkthdr, на которую указывает h, заполняется соответствующими значениями для пакета.

Для них обоих решение одно и то же: вам нужно malloc обновлять указатели для каждого вызова dispatch и копировать в них данные.

Комментарии:

1. Извините, все еще немного запутался. Будет ли это во втором фрагменте кода перед вызовом отправки? или мне нужно было бы сделать копию внутри функции отправки?

2. @finn_101 Не имеет значения, где вы это делаете, просто то, что вы делаете.

3. Имеет смысл. Каков наилучший способ скопировать постоянный символ без знака * ?

4. @finn_101 Если это строка с нулевым завершением, то strdup . Если это просто массив байтов, затем malloc следует memcpy .

5. Как мне получить размер данных? Я пытаюсь strlen(packet) , но каждый раз получается 1 или 2, что, очевидно, неверно