我实现了一个容器,并在它上运行了一些测试。在这个问题上,我注意到了这种行为:
如果我编译它(在这里,cit是我的容器之一):
//...
int i = 0;
while(i != 10)
{
std::cout << *cit << " ";
++cit; ++i;
}
//...然后我打印我期望的数据:
me@LAPTOP-Q8SCO8V5:~/proj/proj_dev$ g++ main.cpp
me@LAPTOP-Q8SCO8V5:~/proj/proj_dev$ ./a.out
5 6 2 4 4 1 2 3 2 7但是,如果条件更改为此循环:
//...
int i = 0;
do {
std::cout << *cit << " ";
++cit; ++i;
} while(cit != mit.end_row(0));
//...我有段错:
me@LAPTOP-Q8SCO8V5:~/proj/proj_dev$ g++ main.cpp
me@LAPTOP-Q8SCO8V5:~/proj/proj_dev$ ./a.out
Segmentation fault (core dumped)我知道循环可能会中断(很可能是这样),因为实现cit或mit.end_row时犯了一些错误。但是在这个例子中,我希望至少在分割错误之前正确地打印第一个元素。对于第一个片段,我相信容器是像我所期望的那样初始化的。
我的问题是,如果我看到的这种行为是由编译器生成的,那么优化代码并找到它最终会导致分段错误。或者如果我错过了什么。
如果需要cit的任何实现代码,我将乐意提供。我没有在我最初的帖子中这样做,因为我不确定这个问题是否需要被发布。
发布于 2020-01-02 16:06:22
std::cout is buffered --输出存储在内存缓存中,而不是立即打印,只有当缓冲区被“刷新”时才会显示。这使您的计算机可以通过等待一个良好的时间来使用块中的输出来优化程序,而不是以单个字符的形式使用,例如,如果您正在写入文件,则等待硬盘处于位置。(想象一下,把每个字符一次一个地写到硬盘上是很慢的!)但是,除非您自己动手,否则无法保证您的机器何时会刷新缓冲区。
在这种情况下,输出将被加载到缓冲区中,但是由于您从未调用std::cout.flush()或打印std::endl (这也会刷新缓冲区),所以不能确定在分段错误之前输出结果。在那之后,所有的赌注都取消了。
发布于 2020-01-02 16:14:34
如果*cit、mit.end_row(0)或operator!=()调用了未定义的行为(例如,取消对容器一端的引用),那么有时它可能会工作,而其他时候则会出现奇怪和无法解释的结果。
您需要识别程序中所有未定义的行为并修复它。
https://stackoverflow.com/questions/59566253
复制相似问题