对不起,制作一个完全可重现的错误版本是非常困难的——所以请用我的原理图代码。
该程序从网页中检索信息,对其进行处理,并将输出保存到 ASCII 文件中。我还有一个“日志”文件(FILE *theLog
---包含在一个Manager
对象中)用于报告错误等。
一些后台方法:
// Prints string to log file
void Manager::logEntry(const string lstr) {
if( theLog != NULL ) { fprintf(theLog, "%s", lstr.c_str()); }
}
// Checks if file with given name already exists
bool fileExists(const string fname) {
FILE *temp;
if( temp = fopen(fname.c_str(), "r") ) {
fclose(temp);
return true;
} else { return false; }
}
// Initialize file for writing (some components omitted)...
bool initFile(FILE *&oFile, const string fname) {
if(oFile = fopen(fname.c_str(), "w") ) { return true; }
else { return false; }
}
造成麻烦的东西:
// Gets data from URL, saves to file 'dataFileName', input control flag 'foreCon'
// stu is some object that has string which i want
bool saveData(Manager *man, Stuff *stu, string dataFileName, const int foreCon) {
char logStr[CHARLIMIT_LARGE]; // CHARLIMIT_LARGE = 2048
sprintf(logStr, "Saving Data...\n");
man->logEntry( string(logStr) ); // This appears fine in 'theLog' correctly
string data = stu->getDataPrefixStr() + getDataFromURL() + "\n"; // fills 'data' with stuff
data += stu->getDataSuffixStr();
if( fileExists(dataFileName) ) {
sprintf(logStr, "save file '%s' already exists.", dataFileName.c_str() );
man->logEntry( string(logStr) );
if( foreCon == -1 ) {
sprintf(logStr, "foreCon = %d, ... exiting.", foreCon); // LINE 'A' : THIS LINE ENDS UP IN OUTPUT FILE
tCase->logEntry( string(logStr) );
return false;
} else {
sprintf(logStr, "foreCon = %d, overwriting file.", foreCon); // LINE 'B' : THIS LINE ENDS UP IN LOG FILE
tCase->logEntry( string(logStr) );
}
}
// Initialize output file
FILE *outFile;
if( !initFile(outFile, dataFileName) ) {
sprintf(logStr, "couldn't initFile '%s'", dataFileName.c_str());
tCase->logEntry( string(logStr) );
return false;
}
fprintf(outFile, "%s", data.c_str()); // print data to output file
if( fclose(outFile) != EOF) {
sprintf(logStr, "saved to '%s'", dataFileName.c_str());
tCase->logEntry( string(logStr) );
return true;
}
return false;
}
如果文件已经存在,并且“ int foreCon
= -1”,那么代码应该将“A”行打印到日志文件中。如果文件存在并且foreCon
!= -1,则旧文件将被覆盖data
。如果文件不存在,则创建它,并将数据写入其中。
然而,结果是数据文件中出现了行'A'的分解版本,并且日志文件中打印了行'B'!!!!
数据文件的样子:
.. exiting.20130127 161456
20130127 000000,55,17,11,0.00
20130127 010000,54,17,11,0.00
... ...
第二行及以后看起来是正确的,但有一个额外的行包含行“A”的一部分。
现在,真正奇怪的部分。如果我注释掉if( foreCon == -1) { ... }
块中的所有内容,则数据文件如下所示:
%d, ... exiting.20130127 161456
20130127 000000,55,17,11,0.00
20130127 010000,54,17,11,0.00
... ...
还有一个额外的行,但它是复制到数据文件中的 LITERAL CODE。
我认为我的代码中有一个 poltergeist。我不明白这怎么可能发生。
编辑:我尝试打印来控制台data
字符串,它给出了相同的混乱值:即%d, ... exiting.20130127 161456
- 所以它必须是关于string
而不是FILE *