奇怪的是,For 循环计数器变量被 .get() 减少了
Strangely For loop counter variable gets reduced by .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
你为什么使用 +1
??
fd.get(vard, vardo_ilgis+1);
缓冲区溢出会损坏一些内存。在一个简单的未优化构建中,损坏的内存可能是循环索引。
the loop count variable gets decreased by fd.get. Why and how even can this happen?
一旦您知道导致未定义行为的原因,许多人会说您不应该调查该未定义行为的详细信息。我不同意。通过了解细节,您可以提高诊断其他您不知道可能调用了哪些未定义行为的情况的能力。
你们所有的局部变量都存储在一起,所以覆盖一个会破坏另一个。
您描述的变量是 "decreased",而实际上它被设置为零。它在归零之前为 1 的事实并不影响它被归零。未定义的行为恰好等同于 i&=~255;
,对于小于 256 的值等于 i=0;
。更偶然的是你可以看到它 i--;
希望清楚为什么 i
在您 运行 没有输入后就停止归零。
fd.get(vard, vardo_ilgis+1);
使缓冲区越界写入。
在你的情况下,你写入的区域(以及你不应该写入的区域)可能与存储 i
的内存区域相同。
但是,最重要的是您最终会遇到著名的不确定行为。这意味着任何事情都可能发生,而试图理解为什么或如何发生是没有意义的(发生的事情是平台、编译器甚至上下文特定的,我认为没有人可以预测或解释它)。
考虑以下代码。此函数从文件中读取一些整数和字符串。
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
你为什么使用 +1
??
fd.get(vard, vardo_ilgis+1);
缓冲区溢出会损坏一些内存。在一个简单的未优化构建中,损坏的内存可能是循环索引。
the loop count variable gets decreased by fd.get. Why and how even can this happen?
一旦您知道导致未定义行为的原因,许多人会说您不应该调查该未定义行为的详细信息。我不同意。通过了解细节,您可以提高诊断其他您不知道可能调用了哪些未定义行为的情况的能力。
你们所有的局部变量都存储在一起,所以覆盖一个会破坏另一个。
您描述的变量是 "decreased",而实际上它被设置为零。它在归零之前为 1 的事实并不影响它被归零。未定义的行为恰好等同于 i&=~255;
,对于小于 256 的值等于 i=0;
。更偶然的是你可以看到它 i--;
希望清楚为什么 i
在您 运行 没有输入后就停止归零。
fd.get(vard, vardo_ilgis+1);
使缓冲区越界写入。
在你的情况下,你写入的区域(以及你不应该写入的区域)可能与存储 i
的内存区域相同。
但是,最重要的是您最终会遇到著名的不确定行为。这意味着任何事情都可能发生,而试图理解为什么或如何发生是没有意义的(发生的事情是平台、编译器甚至上下文特定的,我认为没有人可以预测或解释它)。