使用memcpy重构字符串流的使用
Refactoring use of stringstreams with memcpy
我得到了这个代码:
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下失败,而在正常执行时却没有?
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;
}