【问题标题】:Calling class functions that use character arrays (C++)调用使用字符数组的类函数 (C++)
【发布时间】:2016-06-27 10:33:47
【问题描述】:

我主要使用 C 语言,并且很长一段时间没有使用过类。我正在尝试使用其他人创建的一些类函数,但我无法使 deserialize() 函数工作。我理解它的作用,但我一生都无法弄清楚如何调用这个函数。我在下面提供了函数以及我如何尝试调用它们。

//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

我只是不明白如何调用 deserialize(),我创建了一个数据包并对其进行了序列化,这部分工作正常,但我不明白如何反转它。我需要先创建一个空的数据包对象吗?如果是这样,怎么做?我已经尝试过多种方式,但我无法让它发挥作用。我知道这是非常基本的,但就像我说的那样,我已经有几年没有上课了。我花了很长时间才让序列化工作,但我已经尝试了所有我能想到的反序列化方法并且卡住了。

【问题讨论】:

    标签: c++ function class object serialization


    【解决方案1】:

    @Pongjazzle,

    我同意 Sam 的观点,即课程设计需要改进。不过,我想你可以弄清楚。或许,您可能希望以这种方式测试您的代码,假设 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.
    

    【讨论】:

    • 这成功了!谢谢你。我现在明白我正在创建一个数据包,但没有给它一个可以使用的缓冲区。
    【解决方案2】:

    你使用的类设计得不是很好。

    对于初学者来说,serialize() 函数接受一个指向输出缓冲区的指针,而无需指定缓冲区的大小。相信缓冲区对于“序列化”数据来说足够大。如果不是,它会很乐意在随机存储器上乱涂乱画。

    那么,deserialize() 也令人印象深刻。对于初学者来说,没有自尊的反序列化器需要一个指向被反序列化数据的可变指针。反序列化器应该只需要一个常量或只读指针。

    当然,这个deserialize() 想要一个可变缓冲区的原因是因为它在上面乱写,并通过strtok() 覆盖它正在反序列化的缓冲区。这意味着您不能使用序列化对象来反序列化对象的两个或多个实例,除非您事先制作了序列化对象的副本。

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

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

    【讨论】:

    • 我知道序列化有效,因为我可以打印已序列化的数组。我要问的是你如何调用反序列化等函数。我不担心函数是如何工作的,只是我如何称呼它们。正如我所提到的,我已经有一段时间没有使用过课程并且忘记了基础知识。
    • 看来你打电话给他们就好了。如果你错误地调用它们,你的代码一开始就不会被编译。会出现编译错误。并且仅仅因为您可以打印已序列化的数组,在这种情况下,并不一定意味着您正确分配了缓冲区。我可以很容易地向您展示一个示例 main(),它将某些内容复制到字符缓冲区中,打印缓冲区的内容以显示“它有效”,然后......然后在从 main() 返回时立即出现段错误,因为复制溢出缓冲区,并在整个堆栈中乱扔垃圾。
    • 我明白你在说什么。我已经弄明白了,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    相关资源
    最近更新 更多