我有一个程序,其中一个线程写入文件,其他读取(同步)。但是从一段时间以来,写入和读取的值并不相等。实际上读者读取了正确数量的元素,但值不同。这可能是不将数据推送到磁盘的问题吗?虽然我在写完之后给fflush打电话,但我怎么能确定它是写的,所以我可以拒绝这个版本。 Os - 窗户。
FixedSizeQueue::FixedSizeQueue(const std::string& filename, size_t size)
: size_(size)
, head_(0)
, tail_(0)
{
fopen_s(&file_, filename.c_str(), "w+");
InitializeCriticalSection(&critical_section_);
}
void
FixedSizeQueue::push_values(int* values, size_t count)
{
Logger::report("Called push_values");
EnterCriticalSection(&critical_section_);
size_t free_items = (tail_ > head_) ? size_ - tail_ + head_ : size_ - head_ + tail_;
if (count > free_items)
{
Logger::report("Buffer is full, can't push new values.");
exit(1);
}
size_t till_end = (tail_ >= head_) ? size_ - tail_ : head_ - tail_;
if (count < till_end)
{
fseek(file_, tail_ * sizeof(int), SEEK_SET);
int g = fwrite(values, sizeof(int), count, file_);
assert(g == count);
tail_ += count;
}
else
{
fseek(file_, tail_ * sizeof(int), SEEK_SET);
int h = fwrite(values, sizeof(int), till_end, file_);
assert(h == till_end);
fseek(file_, tail_ * sizeof(int), SEEK_SET);
h = fwrite(values + count, sizeof(int), count - till_end, file_);
assert(h == count - till_end);
tail_ = count - till_end;
}
fflush(file_);
LeaveCriticalSection(&critical_section_);
}
size_t
FixedSizeQueue::get_values(int* values)
{
Logger::report("Called get_values");
EnterCriticalSection(&critical_section_);
const size_t item_count = (tail_ >= head_) ? tail_ - head_ : size_ - head_ + tail_;
if (tail_ > head_)
{
fseek(file_, head_ * sizeof(int), SEEK_SET);
fread(values, sizeof(int), item_count, file_);
}
else
{
fseek(file_, (size_ - head_) * sizeof(int), SEEK_SET);
fread(values, sizeof(int), size_ - head_, file_);
fseek(file_, 0, SEEK_SET);
fread(values + size_ - head_, sizeof(int), tail_, file_);
}
head_ = tail_ = 0;
LeaveCriticalSection(&critical_section_);
return item_count;
}
感谢。
答案 0 :(得分:0)
这篇归档的知识库文章为我们提供了帮助:https://jeffpar.github.io/kbarchive/kb/066/Q66052/
最初使用fopen_s打开文件时,我们将“ c”模式选项作为最后一个选项:
fopen_s( path, "wc") // w - write mode, c - allow immediate commit to disk
请参见https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-s-wfopen-s?view=vs-2019
然后,因为它是Windows,所以当您要强制刷新到磁盘时,请调用
_flushall()
我们在致电
之前先打了这个电话fclose()
我们遇到了您所描述的确切问题,并且此方法已将其解决。
摘自上述知识库文章:
“ Microsoft C / C ++ 7.0版为fopen()引入了” c“模式选项 功能。当应用程序打开文件并指定“ c”模式时, 当运行库将文件缓冲区的内容写入磁盘时, 应用程序调用fflush()或_flushall()函数。 “