【发布时间】:2016-05-13 11:29:52
【问题描述】:
我有这个简单的代码,可以在 pcm wav 文件中使用 fseek 逐步搜索文件中的“数据”:
FILE * waveFile;
waveFile = fopen ( this->fileLocation.c_str ( ), "rb" );
// ... some other code here between, then ... //
int seekTo = 0;
bool found = false;
char data[4];
rewind ( waveFile );
while ( !found && ( fseek ( waveFile, seekTo, SEEK_SET ) == 0 )) {
fread ( data, sizeof ( data ), 1, waveFile );
if (( std::strcmp ( data, "data" ) == 0 ) || ( std::strcmp ( data, "Data" ) == 0 ) || ( std::strcmp ( data, "DATA" ) == 0 )) {
found = true;
fread ( &waveHeader->DATA_SIZE, sizeof ( waveHeader->DATA_SIZE ), 1, waveFile );
}
seekTo++;
}
代码工作正常,它在测试文件上找到数据,读取剩余的数据。由于即使是最大的文件,“数据”也接近开头,所以这段代码对我来说没问题。
但是,当我添加 cpp 标志 -O3 时,代码变得混乱,while 循环永远不会结束。
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3")
我正在使用 cmake + lldb (osx, clion),如果我使用 GDB,也会发生同样的情况。
可能是什么问题,我该如何解决?
PS。我不是想改进你看到的代码,我想了解为什么编译器优化会破解这个 while 循环。
PSS。 这是空终止的工作代码:
int seekTo = 0;
char data[5];
rewind ( waveFile );
while (( fseek ( waveFile, seekTo, SEEK_SET ) == 0 )) {
fread ( data, 4, 1, waveFile );
data[ 4 ] = '\0';
if (( std::strcmp ( data, "data" ) == 0 ) || ( std::strcmp ( data, "Data" ) == 0 ) || ( std::strcmp ( data, "DATA" ) == 0 )) {
fread ( &waveHeader->DATA_SIZE, sizeof ( waveHeader->DATA_SIZE ), 1, waveFile );
break;
}
seekTo += 1;
}
【问题讨论】:
-
std::strcmp ( data, "data" ) == 0的读数超出了data的范围。您忘记了空终止。也许你想memcmp长度为4。 -
您还应该检查
fread是否成功,如果失败则中断循环 -
@M.M 我最初在代码中使用 size_t 检查 fread 并在某些时候返回 0。但是在我拥有的每个文件中都有“数据”,并且在找到任何东西之前就到达了文件末尾。所以我删除了调试的结束检查。
-
如果在 -O3 出现问题,则意味着您的代码存在错误。您应该找到错误而不是进行随机更改(这很可能只是为了使错误的影响出现在其他地方)。如果你的 memset 写的越界,那么它不应该在任何优化级别,如果它没有写越界,那么大概你有一些理由写它,由你的程序逻辑决定,那不会也可以根据优化级别进行更改。
-
您是否幸运(或不幸)取决于如何查看它,您的代码读取(可能写入)超出了数组的范围,这仅取决于该内存中发生了什么以及是否优化器删除了它检测到的任何代码块,它会越界访问等等。除了检查编译器为代码生成的汇编代码之外,您无法得到更详细的答案。
标签: c++ c++11 compiler-optimization fseek