奇怪的是,循环计数器变量减少了.get()

时间:2015-09-21 18:57:08

标签: c++ for-loop get

考虑以下代码。此函数从文件中读取一些整数和字符串。

const int vardo_ilgis = 10;
void skaityti(int &n, int &m, int &tiriama, avys A[])
{
    ifstream fd("test.txt");
    fd >> n >> m >> tiriama;
    fd.ignore(80, '\n');
    char vard[vardo_ilgis]; // <---
    for(int i = 1; i <= n; i++)
    {
        cout << i << ' ';
        fd.get(vard, vardo_ilgis+1); // <---
        cout << i << endl;
        A[i].vardas = vard;
        getline(fd, A[i].DNR);
    }
    fd.close();
}

并输入:

4 6
4
Baltukas   TAGCTT
Bailioji   ATGCAA
Doli       AGGCTC
Smarkuolis AATGAA

在这种情况下,变量'vard'的长度为vardo_ilgis = 10,但在函数fd.get中,读取输入为vardo_ilgis + 1 = 11(大于存储数据的可变长度)。我不是在问如何解决问题,因为显然不要读取比存储在变量上更多的内容。 但是,我真的想了解这种行为的原因:循环计数变量减少了fd.get。为什么以及如何发生这种情况呢?这是这段代码的输出:

1 0
1 0
1 0
1 0
1 1
2 2
3 3
4 4

2 个答案:

答案 0 :(得分:0)

你为什么用+1

fd.get(vard, vardo_ilgis+1);

超越该缓冲区会破坏一些内存。在一个简单的未经优化的构建中,损坏的内存可能是循环索引。

  

循环计数变量减少了fd.get。为什么以及如何发生这种情况呢?

一旦你知道为什么你造成了未定义的行为,许多人说你不应该调查这个未定义行为的细节。我不同意。通过了解详细信息,您可以提高诊断其他情况的能力,在这些情况下您不知道可能调用了哪些未定义的行为。

所有局部变量都存储在一起,因此覆盖一个会倾向于破坏另一个。

您将变量描述为“减少”,而实际上它已设置为零。在归零之前它是1的事实并没有影响它的归零。未定义的行为恰好等同于i&=~255;,其中256以下的值等于i=0;。您可以将其视为i--;

,这更为偶然

希望很明显为什么i在输入用完后停止归零。

答案 1 :(得分:0)

fd.get(vard, vardo_ilgis+1);使缓冲区写入越界。

在您的情况下,您编写的区域(以及您不应该写的区域)可能与存储i的内存区域相同。

但是,最重要的是你最终得到了如此着名的不确定行为。这意味着什么都可能发生,并且没有必要试图理解为什么或如何(平台,编译器甚至特定于上下文的情况会发生什么,我认为任何人都无法预测或解释它。)