gpt4 book ai didi

C++ 未执行的代码改变函数行为?

转载 作者:太空狗 更新时间:2023-10-29 23:05:17 24 4
gpt4 key购买 nike

我使用以下代码(取自 https://codereview.stackexchange.com/questions/22901/reading-all-bytes-from-a-file)在 C++ 中高效地将文件读入数组:

static std::vector<char> ReadAllBytes(char const* filename)
{
std::ifstream ifs(filename, std::ios::binary | std::ios::ate);
std::ifstream::pos_type pos = ifs.tellg();

std::vector<char> result(pos);

ifs.seekg(0, std::ios::beg);
ifs.read(&result[0], pos);

for (unsigned int i = 0; i < result.size(); i++)
if (result.at(i) != 0)
return result; // [1]

//if (!ifs.good()) // Commenting out changes contents of result
// return result; // [2] // Commenting out changes contents of result

return result; // [3]
}

一切正常,[1] 处的断点触发并且函数返回数据(该循环仅用于调试,因为我得到了应该保存数据的 0 填充返回值)。但是,一旦我删除 [2] 处的 If 语句,断点 [3] 就会触发并且数组为空(大小正确,但数组中填充了零)。

从未执行过的代码如何真正改变函数的行为?我认为这可能与堆栈布局有关,事实上我将流和数据保存为局部变量但在堆上手动创建它们会导致完全相同的情况。

你看我完全莫名其妙。我以前从未见过这样的东西。这怎么可能?

PS:我应该补充一点,文件内容是二进制的,文件大小约为 32 MB。

最佳答案

您是否使用优化( Release模式)进行编译?如果是这样,那么如果我不得不猜测,我会说它正在重新排序您的代码。首先,请注意 read 之后的代码实际上都不重要。它所做的只是在所有情况下返回 result 并且不更改数组中的任何内容。许多函数可以内联,这意味着一个好的编译器可以知道这一点并删除所有代码。

这样就可以很容易地解释断点行为。但是添加 if (!ifs.good()) 并让数据为空 - 这很难解释。也许这个关于 read 函数的花絮提供了洞察力:

Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to true). Then (if good), it extracts characters from its associated stream buffer object as if calling its member functions sbumpc or sgetc, and finally destroys the sentry object before returning.

请注意,read 包含对 good() 的检查,这意味着编译器可能正在组合 good() 的两个检查( >read,在内联之后,以及代码中的那个)并使用它来完全跳过读取(?)。这似乎不太可能,但也许它为您指明了调试方向。

我会说我以前在优化器中看到过这个问题。不是 ifstreams 的这个特定问题,而是更普遍的问题,即添加看似未使用的代码会改变行为。最终原因总是因为可以免费重新排序不会改变结果的代码。

关于C++ 未执行的代码改变函数行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20097742/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com