безопасные структуры встраиваемые системы - PullRequest
0 голосов
/ 10 марта 2011

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

Пакет имеет такую ​​структуру "Строка A: Строка B: Строка C".

Например, здесь полученный пакет составлен из трех частей, разделенных с помощью разделителя «:», все эти части должны быть доступны для структуры.

Какой самый эффективный и безопасный способ сделать это.

A.- Создание структуры с атрибутами (partA, PartB PartC), размер которых с критериями, основанными на избегании, превышает этот размер из источника пакета, и добавление также индекса с длиной каждой части вспособ избежать извлечения мусора, этот индикатор длины части может быть меньше или равен 300 (то есть: часть B).

typedef struct parsedPacket_struct {
  char partA[2];int len_partA;
  char partB[300];int len_partB;
  char partC[2];int len_partC;
}parsedPacket;

Проблема здесь в том, что я трачу память, потому что каждая структура должна копироватьСодержимое пакета для каждой структуры, есть способ сохранить только базовый адрес каждой части и все еще использовать len_partX.

Ответы [ 4 ]

4 голосов
/ 10 марта 2011

Как насчет замены (:) на 0 и добавления нуля в конце - тогда у вас есть три символа * для передачи. Вам нужно будет иметь дело со строками нулевой длины, но это может решить эту проблему

1 голос
/ 11 марта 2011

Чтобы избежать повреждения памяти и других переменных, вы обычно объявляете большие буферы данных как статические и размещаете их в области видимости файла, а затем выделяете для них отдельный сегмент ОЗУ. Размещение их в стеке - плохая идея в любой встроенной системе.

Вам необходимо выяснить, существует ли требование выравнивания для ЦП и должен ли код быть переносимым или нет. Компилятор может добавлять любое количество байтов заполнения в любом месте этой структуры, что означает, что вы не сможете сделать это:

parsedPacket pp;

memcpy(&pp, raw_data, sizeof(parsedPacket )) ;

По этой причине структуры , как правило, являются плохим выбором для хранения пакетов данных . Самое безопасное решение - это:

/* packet.h */

typedef struct parsedPacket_struct {
  uint8_t* partA;
  uint8_t* partB;
  uint8_t* partC;

  uint16_t len_partA;
  uint16_t len_partB;
  uint16_t len_partC;

}parsedPacket;


#define MAX_PART_A    2
#define MAX_PART_B  300
#define MAX_PART_C    2


void packet_receive (parsedPacket* packet);



/* packet.c */

static uint8 partA[MAX_PART_A];
static uint8 partB[MAX_PART_B];
static uint8 partC[MAX_PART_C];

void packet_receive (parsedPacket* packet)
{
  /* receive data from server */
  ...

  packet->len_partA = ...;
  packet->len_partB = ...;
  packet->len_partC = ...;

  packet->partA = partA;
  packet->partB = partB;
  packet->partC = partC;

  memcpy(partA, A_from_server, packet->len_partA);
  memcpy(partB, B_from_server, packet->len_partB);
  memcpy(partC, C_from_server, packet->len_partC);
}

Это может быть расширено, чтобы при необходимости содержать несколько статических буферов, то есть статический массив массивов для каждого буфера. Поскольку вы имеете дело с большими объемами данных во встроенной системе, вы никогда не можете позволить программе складывать буферы по прихоти. Максимальное количество копий полученного пакета должно быть определено при разработке программы.

0 голосов
/ 11 марта 2011

Я не уверен, почему вы думаете, что ваш подход тратит память, но вот что я бы сделал, если бы чувствовал себя особенно хакерским:

typedef struct {
  char *a, *b, *c;
  char data[1]; // or 0 if your compiler lets you, or nothing in C99
} parsedPacket;

Это называется членом гибкого массива. По сути, когда вы выделяете память для своей структуры, вы делаете это:

parsedPacket *p = malloc(offsetof(parsedPacket, data[N]));

N выше - это объем данных, который нужен вашему массиву, т. Е. Какова длина прочитанной строки Это распределяет структуру так, чтобы элемент data имел размер, достаточный для всей вашей строки данных. Затем скопируйте полученную строку в этот элемент, замените ':' символов на '\0' и установите a для первой строки (т. Е. p->a = p->data), b для второй (p->b = p->data + strlen(p->a) + 1) и c к третьему. Конечно, вы можете упростить этот процесс, выполнив все сразу:

size_t current = 0;
p->a = p->data;
p->b = p->c = NULL;
while(1)
  {
    int i = getc();
    if(i == '\n' || i == EOF) break; // or whatever end conditions you expect
    if(i == ':')
      {
        p->data[current] = '\0';
        ++current;
        if(p->b == NULL) p->b = &p->data[current];
        else if(p->c == NULL) p->c = &p->data[current];
        else /* error */;
      }
    else
      {
        p->data[current] = i;
      }
  }
0 голосов
/ 10 марта 2011

Тип каждого len_partN должен быть типом, который может рассчитывать до длины partN.Например:

typedef struct parsedPacket_struct {
  char partA[300];unsigned short len_partA; // unsigned shorts have < 32k distinct values
  char partB[300];unsigned short len_partB; 
  char partC[300];unsigned short len_partC; 
}parsedPacket;

Это похоже на дизайнерское решение.Если вы хотите, чтобы структура легко создавалась, используйте описанный выше подход, но остерегайтесь ее недостатков (например, «что если B имеет более 300 символов?»).

...