2016-03-12 3 views
1

Я в основном работаю с C и не использовал классы в течение довольно длительного времени. Я пытаюсь использовать некоторые функции класса, созданные кем-то другим, но я не могу заставить функцию deserialize() работать. Я понимаю, что он делает, но я не могу для жизни понять, как назвать эту функцию. Я предоставил функции и как я пытаюсь их назвать.Вызов функций класса, использующих массивы символов (C++)

//Creates a packet 
packet::packet(int t, int s, int l, char * d){ 
    type = t; 
    seqnum = s; 
    length = l; 
    data = d; 
} 
// This function serializes the data such that type, seqnum, length, and data values are placed 
// in a char array, spacket, and separated by a single space; that is, spacket contains the serialized data 
void packet::serialize(char * spacket){ 
     cout << "data: " << endl << endl; 
    sprintf (spacket, "%d %d %d %s", type, seqnum, length, data); 
} 

// This function deserializes a char array, spacket, which is the result of a call to serialize 
void packet::deserialize(char * spacket){ 
    char * itr; 
    itr = strtok(spacket," "); 
    char * null_end; 

    this->type = strtol(itr, &null_end, 10); 

    itr = strtok(NULL, " "); 
    this->seqnum = strtol (itr, &null_end, 10); 

    itr = strtok(NULL, " "); 
    this->length = strtol (itr, &null_end, 10); 

    if(this->length == 0){ 
     data = NULL; 
    } 
    else{ 
     itr = strtok(NULL, ""); 
     for(int i=0; i < this->length; i++){ // copy data into char array 
      this->data[i] = itr[i]; 
     } 
    } 
} 

А вот как я пытаюсь получить эту работу:

packet *test = new packet(1, 4, 4, message); //message is a *char with the data 
test->serialize(sendbuf);   //this works correctly 
packet *test2 = new packet(0,0,0, NULL); //I am not sure if I need to be creating a new packet for the deserialized information to get placed into 
test->deserialize(sendbuf); //results in a segmentation fault currently 

Я просто не понимаю, как назвать десериализации(), я создал пакет и сериализовать его и часть отлично работает, но я не понимаю, как ее отменить. Нужно ли сначала создавать пустой пакетный объект? Если да, то как? Я попытался сделать это несколькими способами, но я не могу заставить его работать. Я знаю, что это очень просто, но, как я уже сказал, я не работал с классами через пару лет. Мне потребовалось довольно много времени, чтобы сериализовать работу, но я попробовал все, что мог придумать для десериализации и застрял.

ответ

1

@Pongjazzle,

Я согласен с Сэмом, что дизайн класс нуждается в усовершенствовании. Однако, я думаю, вы можете понять это. Возможно, вы захотите сделать это таким образом, чтобы проверить свой код, предполагая, что sendbuf может хранить все сериализованные пакетные данные.

packet *test = new packet(1, 4, 4, message); 
test->serialize(sendbuf); 

packet *test2 = new packet(0,0,0, NULL); // results in a segmentation fault currently (which is expected as the attempts to access a location referred to by a null pointer in this->data (i.e., NULL based on the object instantiation code) 
test->deserialize(sendbuf); 

Изменить это:

packet *test2 = new packet(0,0,0, newmessage); // assign a valid buffer 
test2->deserialize(sendbuf); // Now fill's in the values and buffer from serialized content. 
+0

Это сработало! Спасибо. Теперь я понимаю, что создаю пакет, но не предоставляю ему буфер для работы. – Pongjazzle

1

Класс, который вы используете, не очень хорошо разработан.

Для начала функция serialize() принимает указатель на выходной буфер без каких-либо средств для указания размера буфера. Он верит, что буфер будет достаточно большим для «сериализованных» данных. Если это не так, это будет счастливой каракули над случайной памятью.

Затем, deserialize() также впечатляет. Во-первых, ни один уважающий себя десериализатор не требует изменчивого указателя на десериализованные данные. Для десериализатора требуется только константа или указатель только для чтения.

Конечно, причина, по которой этот deserialize() требует изменчивого буфера, заключается в том, что он перебирает и перезаписывает через strtok() буфер, который десериализуется. Это означает, что вы не можете использовать сериализованный объект для десериализации двух или более экземпляров объекта, если вы заранее не сделаете копию сериализованного объекта.

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

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

+0

Я знаю сериализации работает, потому что я могу напечатать массив, который был сериализован. Все, о чем я спрашиваю, это то, как вы называете функцию, такую ​​как десериализация.Я не беспокоюсь о том, как работают функции, как я их называю. Как я уже говорил, я не работал с занятиями и забыл об основах. – Pongjazzle

+0

Кажется, вы их так называете. Если вы их неправильно назовете, ваш код не будет скомпилирован в первую очередь. Ошибка компиляции. И только потому, что вы можете распечатать массив, который был сериализован, в этом контексте это не обязательно означает, что вы правильно распределили буфер. Я мог бы легко показать вам образец main(), который копирует что-то в буфер символов, печатает содержимое буфера, чтобы показать, что «он работает», и ... затем немедленно segfaults при возврате из main(), потому что копия перегружена буфера и обломаны по всему стеку. –

+0

Я вижу, что вы говорите. Я понял, теперь спасибо! – Pongjazzle