0

我得到了这个代码:

  class Record
    {
   private:
      unsigned short size_of_buffer;
      char* buffer;

   public:
      bool was_marked_as_deleted();
    };  


bool Record::was_marked_as_deleted(){

        if (buffer == NULL)
            return false;

        stringstream stream;
        stream.write(buffer,size_of_buffer);
        stream.seekg(0,stream.beg);

        unsigned short size_of_first_field = 0;
        stream.read( (char*)(&size_of_first_field) , sizeof(size_of_first_field) );

        if (size_of_first_field > 1)
            return false;

        char first_field = 1;
        stream.read( (char*)(&first_field) , sizeof(first_field) );
        if ( first_field != MARK_DELETED )
            return false;

        return true; 

    }

上面的函数是

  • 非常低效,因为stream.write(buffer,size_of_buffer);线路
  • 不可读。

所以我想使用memcpy而不是重构它stringstreams。这就是我想出的:

bool Record::was_marked_as_deleted(){

    if(buffer==NULL)
        return false;

    unsigned short size_of_first_field= 0;
    memcpy(&size_of_first_field,buffer,sizeof(size_of_first_field));

    if (size_of_first_field > 1)
        return false;

    char first_field = 1;

    //This line produces valgrind error
    //EDIT: fixed it with the following IF statement
    if (size_of_buffer > sizeof(size_of_first_field))
         memcpy(&first_field,buffer+sizeof(size_of_first_field),sizeof(first_field));

    if (first_field != MARK_DELETED )
        return false;

    return true;
}

现在,问题是我的程序运行良好,但是当我使用 运行它时valgrind,我得到了这个:

==17340== Invalid read of size 1
==17340==    at 0x8059452: Record::was_marked_as_deleted() (Record.cpp:161)
==17340==  Address 0x5af2832 is 0 bytes after a block of size 2 alloc'd

为什么是这样?为什么我的程序在 valgrind 下失败,但在正常执行时却没有?

4

1 回答 1

1

std::stringstream对于这种类型的操作,两者memcpy都是低效的。只需像这样直接访问缓冲区...

bool Record::was_marked_as_deleted()
{
    if (buffer == NULL || size_of_buffer < 3)
        return false;

    unsigned short size_of_first_field
        = reinterpret_cast<unsigned short*>(buffer)[0];

    if (size_of_first_field > 1)
        return false;

    if (buffer[3] != MARK_DELETED)
        return false;

    return true;
}

或者使用数据结构...

bool Record::was_marked_as_deleted()
{
    if (buffer == NULL || size_of_buffer < 3)
        return false;

    // Add packing directives if necessary. i.e. #pragma pack
    struct Data { unsigned short size; char flag; };

    Data *field = reinterpret_cast<Data*>(buffer);

    if (field->size > 1)
        return false;

    if (field->flag != MARK_DELETED)
        return false;

    return true;
}
于 2013-07-02T19:09:33.377 回答