gpt4 book ai didi

c++ - 当 struct 将零长度数组作为唯一成员时,数组下标越界

转载 作者:行者123 更新时间:2023-12-03 09:26:06 27 4
gpt4 key购买 nike

在以下代码中:

#include <cstring>

template <unsigned len>
struct CharArray {
CharArray() {
memset(data_, 0, len);
}
char data_[len];
};

struct Foobar {
CharArray<5> a;
CharArray<3> b;
CharArray<0> c;
};

int main() {
Foobar f;
}
型号 CharArray<0>最终将一个零大小的数组作为其唯一成员。我知道这是一个 GCC 扩展和一般不安全的做法。问题不在于那个。
当我用 gcc 10.2.0 编译代码时,我收到以下警告:
<source>: In function 'int main()':
<source>:5:3: warning: array subscript 8 is outside array bounds of 'Foobar [1]' [-Warray-bounds]
5 | CharArray() {
| ^~~~~~~~~
<source>:18:10: note: while referencing 'f'
18 | Foobar f;
| ^
使用 gcc9 及更早版本没有警告。
问:下标8从哪里来?什么是 Foobar [1]有提到吗?看起来有一个 Foobars 的数组,我们正在尝试访问该数组中的元素 8。不知道怎么会这样。如果有人知道细节,如果你能解释一下,我将不胜感激。
使用 gcc++-10 编译时会发生这种情况在 Ubuntu 20.04 中使用 -O3 -Wall -Wextra作为选项。如果我没有通过任何优化标志,就不会有任何警告。另外:如果我拿走构造函数,警告也会消失。

最佳答案

该问题似乎与 memset() 有某种关系。 :由于使用条件( len != 0 )来避免它不起作用,似乎编译器认识到 CharArray<0> 的起始地址的对象是由 CharArray<3> 的初始化产生的并就此发出警告。这个理论可以通过有条件地不初始化 CharArray<3> 来检验。与 memset()或专门用于使警告生效的类型:

CharArray() { if (len != 3) memset(data_, 0, len); }
或者
template <>
struct CharArray<3> {
CharArray(): data_() { }
char data_[3];
};
该警告可能是虚假的。似乎在使用零大小数组的地址时,编译器已经“忘记”它是通过访问不同数组的成员产生的。避免警告的最简单方法似乎是正确初始化 data在初始值设定项列表中并且不使用 memset()根本:
template <unsigned len>
struct CharArray {
CharArray(): data_() {}
char data_[len];
};

关于c++ - 当 struct 将零长度数组作为唯一成员时,数组下标越界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65405795/

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