Изменения указателя на последней итерации цикла foor - PullRequest
0 голосов
/ 12 сентября 2018

Я пытаюсь реализовать потоковый приемник ACN в C ++.Для этого я создал сокет, который получает данные из тестового источника, который я получил из Интернета, но работает локально.Я получаю данные просто отлично.Однако, когда я перебираю отдельные байты вектора в корневом слое, используемый мной указатель внезапно меняется на последней итерации цикла for.

Код, который я использую для проверки полей в корневом слое, выглядит следующим образом.

// Locations for each field of the root layer in the packet in the raw data
char *preamble_size_p    = &this->raw[0];
char *postamble_size_p   = &this->raw[2];
char *acn_pid_p          = &this->raw[4];
char *flags_and_length_p = &this->raw[16];
char * const vector_p    = &this->raw[18];

int i;
uint8_t acn_pid_byte;

// get preamble size and check it
memcpy(&this->packet.root_layer.preamble_size, preamble_size_p, 2);
this->packet.root_layer.preamble_size = htons(this->packet.root_layer.preamble_size);
if (this->packet.root_layer.preamble_size != PREAMBLE_SIZE)
    return PACKET_ERROR_INVALID_PREAMBLE_SIZE;

// get postamble size and check it
memcpy(&this->packet.root_layer.postamble_size, postamble_size_p, 2);
this->packet.root_layer.postamble_size = htons(this->packet.root_layer.postamble_size);
if (this->packet.root_layer.postamble_size != POSTAMBLE_SIZE)
    return PACKET_ERROR_INVALID_POSTAMBLE_SIZE;

// get ACN pid and check if valid
for (i = 0; i < ACN_PID_SIZE; i++) {
    memcpy(&acn_pid_byte, acn_pid_p + i, 1);
    if (acn_pid_byte != ACN_PID[i]) {
        return PACKET_ERROR_INVALID_ACN_PID;
    }
    this->packet.root_layer.acn_pid[i] = acn_pid_byte;
}

// get flags and length
memcpy(&this->packet.root_layer.flength, flags_and_length_p, 2);
this->packet.root_layer.flength = htons(this->packet.root_layer.flength);

/* ERROR HAPPENS IN LOOP BELOW */

// get vector and check if valid
uint32_t vector_bytes;
for (int k = 0; k < 4; k++) {
    memcpy(&vector_bytes + k, vector_p + k, 1);
}

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

raw - это просто char *raw, который назначен в конструкторе класса и содержит байты, которые моя программа получает из источника.

char *raw;  
int size;

Packet(char *raw, int size) {
    this->raw = raw;
    this->size = size;
}

Код для получения данных.

char buffer[MAXLINE] = {0}; // MAXLINE is 1024
n = recvfrom(sock_fd, (char *)buffer, MAXLINE, MSG_WAITALL, ( struct sockaddr *) &cli_addr, &len);
Packet packet = Packet(buffer, n);

Сразу после этого вызывается packet.process(), который начинает выполнение кода в верхнем блоке кода.

Я попытался установить точку наблюдения в GDB, и это результат.

Breakpoint 1, Packet::processRootLayer (this=0x7fffffffd5e0) at server.cpp:45
45          memcpy(&this->packet.root_layer.preamble_size, preamble_size_p, 2);
(gdb) watch vector_p
Hardware watchpoint 2: vector_p
(gdb) c
Continuing.

Hardware watchpoint 2: vector_p

Old value = 0x7fffffffdcc2 ""
New value = 0x7fffffffdc00 ""
Packet::processRootLayer (this=0x7fffffffd5e0) at server.cpp:71
71          for (int k = 0; k < 4; k++) {
(gdb) 

Буду признателен за любую помощь, и если вам нужна дополнительная информация, пожалуйста, дайте мне знать.

1 Ответ

0 голосов
/ 12 сентября 2018

Ваша переменная vector_bytes имеет тип uint32_t, поэтому &vector_bytes + k не добавляет k байтов к &vector_bytes, а добавляет k*sizeof(uint32_t) байтов.В результате ваш memcpy перезаписывает другие переменные в вашей программе.

Вы можете добавить приведение, например,

uint32_t vector_bytes;
for (int k = 0; k < 4; k++) {
    memcpy((char*)&vector_bytes + k, vector_p + k, 1);
}

, или вы можете сделать это без цикла.

uint32_t vector_bytes;
memcpy(&vector_bytes, vector_p, 4);

Намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...