我正在创建一个包含一些数据对象的文件。数据对象有不同的大小,就像这样(非常简化):
struct Data{
uint64_t size;
char blob[MAX_SIZE];
// ... methods here:
}
稍后一步,文件将在内存中为mmap(),
所以我希望每个数据对象的开头都是在8个字节对齐的内存地址上开始的,其中uint64_t size
将被存储(让我们忽略字节序)。
代码看起来或多或少(目前硬编码的8个字节):
size_t calcAlign(size_t const value, size_t const align_size){
return align_size - value % align_size;
}
template<class ITERATOR>
void process(std::ofstream &file_data, ITERATOR begin, ITERATOR end){
for(auto it = begin; it != end; ++it){
const auto &data = *it;
size_t bytesWriten = data.writeToFile(file_data);
size_t const alignToBeAdded = calcAlign(bytesWriten, 8);
if (alignToBeAdded != 8){
uint64_t const placeholder = 0;
file_data.write( (const char *) & placeholder, (std::streamsize) alignToBeAdded);
}
}
}
这是在文件中实现对齐的最佳方法吗?
答案 0 :(得分:2)
您不需要依赖writeToFile
来返回尺寸,您可以使用ofstream::tellp
const auto beginPos = file_data.tellp();
// write stuff to file
const auto alignSize = (file_data.tellp()-beginPos)%8;
if(alignSize)
file_data.write("\0\0\0\0\0\0\0\0",8-alignSize);
编辑OP评论: 测试了一个最小的例子,它可以工作。
#include <iostream>
#include <fstream>
int main(){
using namespace std;
ofstream file_data;
file_data.open("tempfile.dat", ios::out | ios::binary);
const auto beginPos = file_data.tellp();
file_data.write("something", 9);
const auto alignSize = (file_data.tellp() - beginPos) % 8;
if (alignSize)
file_data.write("\0\0\0\0\0\0\0\0", 8 - alignSize);
file_data.close();
return 0;
}
答案 1 :(得分:1)
您可以通过操作输入缓冲区而不是文件处理来优化过程。修改您的Data结构,以便填充缓冲区的代码负责对齐。
struct Data{
uint64_t size;
char blob[MAX_SIZE];
// ... other methods here
// Ensure buffer alignment
static_assert(MAX_SIZE % 8 != 0, "blob size must be aligned to 8 bytes to avoid Buffer Overflow.");
uint64_t Fill(const char* data, uint64_t dataLength) {
// Validations...
memcpy(this->blob, data, dataLength);
this->size = dataLength;
const auto paddingLen = calcAlign(dataLength, 8) % 8;
if (padding > 0) {
memset(this->blob + dataLength, 0, paddingLen);
}
// Return the aligned size
return dataLength + paddingLen;
}
};
现在,当您将数据传递给&#34;过程&#34;函数只使用Fill返回的大小,确保8字节对齐。 这样您仍然可以手动处理对齐,但是您不必对文件进行两次写入。
注意:此代码假定您也使用Data作为输入缓冲区。如果您的代码在将缓冲区写入文件之前使用其他对象来保存缓冲区,则应使用相同的主体。
如果您可以使用POSIX,请参阅pwrite