C++ C++;测试文件生成器生成不一致的数据
假设该程序根据用户提供的参数生成测试文件。该文件模拟具有第一个参数fileNumber的命令。例如:C++ C++;测试文件生成器生成不一致的数据,c++,C++,假设该程序根据用户提供的参数生成测试文件。该文件模拟具有第一个参数fileNumber的命令。例如: START 1 WRITE 1 1 WRITE 1 1 READ 1 1 START 2 READ 1 1 ... ... READ 2 1 END 1 WRITE 1 2 WRITE 1 2 READ 2 2 WRITE 1 1 WRITE 1 2 WRITE 1 2 WRITE 2 3 WRITE 2 4 WRITE 2 5 END 2 问题是结束文件号之后的行不应再对该文件号执行任何操作
START 1
WRITE 1 1
WRITE 1 1
READ 1 1
START 2
READ 1 1
...
...
READ 2 1
END 1
WRITE 1 2
WRITE 1 2
READ 2 2
WRITE 1 1
WRITE 1 2
WRITE 1 2
WRITE 2 3
WRITE 2 4
WRITE 2 5
END 2
问题是结束文件号
之后的行不应再对该文件号执行任何操作
上面的示例文本文件是由生成器生成的,并演示了问题:在第行结束1
之后,仍然有多个写入1*
代码如下:
int main(int argc, char **argv){
if(argc < 4){
usage(argv[0]);
exit(EXIT_FAILURE);
}
// extract command line arguments
std::stringstream ss;
int diskCapacity = atoi(argv[1]);// ss << argv[1]; ss >> diskCapacity;
int writeRatio = atoi(argv[2]);// ss << argv[2]; ss >> writeRatio;
char *ofileName = argv[3];
// validate writeRatio
if( (writeRatio < 0) || (writeRatio > 100) ) {
std::cerr << argv[0] << ": writeRatio out of range [0,100]: " << writeRatio << std::endl;
exit(EXIT_FAILURE);
}
std::ofstream outfile;
outfile.open(ofileName);
// seed rng
std::chrono::high_resolution_clock::time_point time = std::chrono::high_resolution_clock::now();
std::minstd_rand rng(time.time_since_epoch().count());
/***** generate simluation sequence *****/
int diskSize = 0;
std::vector<File> aliveFiles;
int new_fid = 1;
int nFilesCreated = 0;
// create at least 1 file
File f;
f.id = new_fid++;
f.size = 1;
aliveFiles.push_back(f);
diskSize++;
nFilesCreated++;
outfile << start(f.id) << std::endl;
do {
// start
if( ((rng()%10) < 2) && (nFilesCreated < diskCapacity/4) ){
// new file
f.id = new_fid++;
f.size = 1;
// add to disk
aliveFiles.push_back(f);
diskSize++;
nFilesCreated++;
outfile << start(f.id) << std::endl;
continue;
}
// choose a file
int new_fsize = -1;
int new_fid = -1;
if(!aliveFiles.empty()) {
std::random_shuffle(aliveFiles.begin(), aliveFiles.end());
new_fid = (aliveFiles.back()).id;
new_fsize = (aliveFiles.back()).size;
}
else {
break;
}
// write
if( (int)(rng() % 100) < writeRatio ) {
// writeRatio% chance to write
int block = 1 + (rng() % new_fsize);
File newFile;
if(block == new_fsize) {
// writing new block
diskSize++;
new_fsize++;
newFile.id = new_fid;
newFile.size = new_fsize;
aliveFiles.pop_back();
aliveFiles.push_back(newFile);
}
outfile << write(newFile.id, block) << std::endl;
continue;
}
// end/read
if(rng() % 100 == 0) {
// end
aliveFiles.pop_back();
outfile << end(new_fid) << std::endl;
}
else {
if( (int)(rng() % 100) < (100-writeRatio) ){
// (100-writeRatio)% chance to read
if(new_fsize > 1) {
int block = 1 + (rng() % (new_fsize-1));
outfile << read(new_fid, block) << std::endl;
}
}
}
} while(diskSize < diskCapacity);
// check that all files have ended, if not then clean up
while(!aliveFiles.empty()) {
new_fid = (aliveFiles.back()).id;
aliveFiles.pop_back();
outfile << end(new_fid) << std::endl;
}
return 0;
}
int main(int argc,char**argv){
如果(argc<4){
用法(argv[0]);
退出(退出失败);
}
//提取命令行参数
std::stringstream-ss;
int diskCapacity=atoi(argv[1]);//ss>diskCapacity;
int writeRatio=atoi(argv[2]);//ss>writeRatio;
char*ofileName=argv[3];
//验证写入
如果((写操作<0)| |(写操作>100)){
std::cerr错误相当严重。如果查看测试数据,您会注意到错误的文件号只出现在写入
行中,而不会出现在读取
行中
这将问题缩小到代码的这一部分,即使用变量newFile
,而不首先初始化它:
// write
if((int)(rng() % 100) < writeRatio) {
// writeRatio% chance to write
int block = 1 + (rng() % new_fsize);
File newFile; // <===== unitialized !!
if(block == new_fsize) { // <===== what happens if this is false ?
// writing new block
diskSize++;
new_fsize++;
newFile.id = new_fid;
newFile.size = new_fsize;
aliveFiles.pop_back();
aliveFiles.push_back(newFile);
}
outfile << write(newFile.id, block) << std::endl; // <== OUCH, if the if condition failed you go here with random data in newFile !!
continue;
}
//写
如果((int)(rng()%100) File newFile;//捕捉得很好。我花了一整晚都没找到这个bug。@firefly注意新的_fid变量。它定义了两次,一次在do/while之外,一次在do/while中。可能不是你想要的。@user4581301这也是一个非常好的拍摄方法!恭喜!而且非常糟糕:循环体的第一部分指循环外的新fid,但循环的第二部分会被重新定义。你可能在另一个晚上救了firefly。它可能会做OP希望它做的事情,因为内部新fid在程序使用外部新fid完成之前不应该被推到堆栈上,但是如果出现了一些漂亮的优化,上帝会帮助他或她编译器中的ck有一个更好的想法。