C++ 调用使用字符数组(C+;+;)的类函数

C++ 调用使用字符数组(C+;+;)的类函数,c++,function,class,object,serialization,C++,Function,Class,Object,Serialization,我主要使用C语言,有一段时间没有使用过类。我试图使用其他人创建的一些类函数,但无法使反序列化()函数正常工作。我理解它的功能,但我一辈子都不知道如何调用这个函数。我在下面提供了函数以及如何调用它们 //Creates a packet packet::packet(int t, int s, int l, char * d){ type = t; seqnum = s; length = l; data = d; } // This function seria

我主要使用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];
        }
    }
}

我只是不知道如何调用deserialize(),我已经创建了一个数据包并将其序列化,这部分工作正常,但我不知道如何反转它。我需要先创建一个空包对象吗?如果是,怎么做?我尝试过多种方法,但都无法成功。我知道这是非常基本的,但正如我所说的,我已经有两年没有上过课了。我花了很长时间才开始序列化工作,但我已经尝试了所有我能想到的反序列化方法,我被卡住了。

您使用的类设计得不是很好

对于初学者来说,
serialize()
函数获取指向输出缓冲区的指针,而没有任何方法来指定缓冲区的大小。它相信缓冲区将足够大以容纳“序列化”数据。如果不是,它会很高兴在随机内存上乱涂乱画

然后,
反序列化()
也令人印象深刻。对于初学者来说,任何自尊的反序列化程序都不需要指向被反序列化数据的可变指针。反序列化程序应该只需要常量或只读指针

当然,这个
反序列化()
需要一个可变缓冲区的原因是,它通过反序列化的缓冲区
strtok
()进行涂鸦和覆盖。这意味着您不能使用序列化对象来反序列化该对象的两个或多个实例,除非您事先制作了序列化对象的副本

从您所展示的内容来看,实际上并不清楚实际的bug在哪里,但很可能是因为您没有为序列化对象分配足够大的缓冲区。即使您相信“它工作正常”,但它没有,并最终损坏了内存,直到代码尝试反序列化损坏的缓冲区,导致未定义的行为,这才变得明显

但是,如果您确实认为缓冲区足够大,那么您应该能够通过使用调试器逐步检查代码并检查它在做什么来自己找出答案。对于运行时涉及分段错误的问题,正确的答案是始终使用调试器,检查应用程序的运行时状态并确定问题。

@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.

我知道serialize可以工作,因为我可以打印已序列化的数组。我要问的是如何调用反序列化之类的函数。我不担心函数如何工作,只担心如何调用它们。正如我所提到的,我已经有一段时间没上过课了,忘记了一些基本的东西。看来你说它们很好。如果调用错误,您的代码一开始就不会被编译。可能会有编译错误。在这种情况下,仅仅因为可以打印已序列化的数组,并不一定意味着您正确分配了缓冲区。我可以很容易地向您展示一个示例main(),它将某些内容复制到字符缓冲区,打印缓冲区的内容以显示“它可以工作”,然后。。。然后在从main()返回时立即segfaults,因为副本超出了缓冲区,并且在堆栈上到处都是垃圾。我明白你的意思了。我现在明白了,谢谢!这成功了!非常感谢。我现在明白了,我正在创建一个数据包,但没有给它一个缓冲区。
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.