Ошибка сегментации в функции сериализации

Проблема в переменной MSG. Каждое сообщение может иметь размер, который может меняться, поэтому переменная payload_len. Не могу определить ошибку в коде. Все мои попытки привели к "ошибке сегментации".

ПКГ

typedef struct pkg{
    uint32_t payload_len;
    uint32_t psecret;
    uint16_t step;
    uint16_t student_num;
    char* msg;
}Pkg;

построить функцию

Pkg* constructPKG(int payload_len, int psecret, short step, char* msg){

    Pkg* pkgS = (Pkg*) malloc(sizeof(Pkg));
    pkgS->payload_len = payload_len;
    pkgS->psecret = psecret;
    pkgS->step = step;
    pkgS->student_num = STUDENT_NUM;
    pkgS->msg=msg;
    return pkgS;
}

Функция сериализации

void serialize(Pkg* pkgS, char *data){
    uint32_t temp_32;
    uint16_t temp_16;

    temp_32 = htonl(pkgS->payload_len);
    memcpy(&data[0], &temp_32, sizeof(temp_32));

    temp_32 = htonl(pkgS->psecret);
    memcpy(&data[4], &temp_32, sizeof(temp_32));

    temp_16 = htons(pkgS->step);
    memcpy(&data[8], &temp_16, sizeof(temp_16));

    temp_16 = htons(pkgS->student_num);
    memcpy(&data[10], &temp_16, sizeof(temp_16));

    int x = pkgS->payload_len;
    char msg[x];
    memcpy(&data[12], &pkgS->msg,sizeof(msg));

}

Десериализовать функцию

void deserialize(char *data, Pkg* pkgs){
    uint32_t temp_32;
    uint16_t temp_16;


    memcpy(&temp_32, &data[0], sizeof(temp_32));
    pkgs->payload_len=ntohl(temp_32);

    memcpy(&temp_32, &data[4], sizeof(temp_32));
    pkgs->psecret=ntohl(temp_32);

    memcpy(&temp_16, &data[8], sizeof(temp_16));
    pkgs->step=ntohs(temp_16);

    memcpy(&temp_16, &data[10], sizeof(temp_16));
    pkgs->student_num=ntohs(temp_16);

    int x = pkgs->payload_len;
    char msg[x];
    memcpy(&pkgs->msg[0], &data[12], sizeof(msg));
}

Функция печати

void printPkg(Pkg* pkgS){
    printf("Payload_len: %d\n",pkgS->payload_len);
    printf("Psecret: %d\n",pkgS->psecret);
    printf("Step: %d\n",pkgS->step);
    printf("Student_num: %d\n",pkgS->student_num);
    printf("MSG: %s\n",pkgS->msg);
}

пожалуйста, покажите код, где вы резервируете память для pkgS->msg перед вызовом десериализации (или сериализации); параметр constructionпросто убийц msg...

Stephan Lechner 10.06.2019 23:26

` char *hello = "Привет, мир"; символ *данные; Pkg *x = конструкцияPKG(strlen(привет), 12, 2, привет); Пакет *y = конструкцияPKG(0, 0, 0, NULL);`

Jeferson Juliani 10.06.2019 23:33

@JefersonJuliani Добавляйте в вопрос код, а не комментарии.

Barmar 10.06.2019 23:34

Вам не нужна переменная msg. sizeof(msg) то же, что x.

Barmar 10.06.2019 23:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы копируете указатель msg, а не данные, на которые он указывает. Но вы используете длину полезной нагрузки, поэтому вы получаете доступ за пределы struct if payload_len > sizeof(char*).

Изменять

int x = pkgS->payload_len;
char msg[x];
memcpy(&data[12], &pkgS->msg,sizeof(msg));

к

char msg[x];
memcpy(&data[12], pkgS->msg, pgkS->payload_len);

А в функции deserialize() вам нужно выделить место для msg перед копированием в нее. Изменять:

int x = pkgs->payload_len;
char msg[x];
memcpy(&pkgs->msg[0], &data[12], sizeof(msg));

к

pkgs->msg = malloc(pkgs->payload_len);
memcpy(pkgs->msg, &data[12], pkgs->payload_len);

Я вижу две проблемы в вашем коде, которые выглядят подозрительно:

Во-первых, в вашей функции сериализации вы передаете адрес указателя (а не значение указателя) в memcpy. Это приведет к неопределенному поведению (чтение из памяти, которая не принадлежит допустимому объекту). Изменить

int x = pkgS->payload_len;
char msg[x];
memcpy(&data[12], &pkgS->msg,sizeof(msg));

к ...

memcpy(&data[12], pkgS->msg, pkgS->payload_len);

Во-вторых, при десериализации вы копируете в pkgs->msg, но, похоже, у вас не было зарезервировано памяти для него (в комментарии вы пишете, что передаете NULL в construct-функцию. Вместо

int x = pkgs->payload_len;
char msg[x];
memcpy(&pkgs->msg[0], &data[12], sizeof(msg));

Напишите

pkgs->msg = malloc(pkgs->payload_len);
memcpy(&pkgs->msg[0], &data[12], pkgs->payload_len);

Другие вопросы по теме