在结构中设置数组元素时出现总线错误

Posted

技术标签:

【中文标题】在结构中设置数组元素时出现总线错误【英文标题】:Bus error when setting array element in struct 【发布时间】:2020-04-14 08:08:41 【问题描述】:

我有以下结构:

struct State 
    int num_walls;
    Wall walls[];

    int num_persons;
    Person persons[];
;

我想让 Persons 包含两个 Persons,而墙壁包含一个 Wall:

int num_walls = 1;
int num_preson = 2;

State simState = *(State*)malloc( sizeof(simState) + num_person*sizeof(Person) + num_walls*sizeof(Wall));
simState.num_walls = num_walls;
simState.num_persons = num_person;
simState.walls[0] = w;
simState.persons[0] = p1;
simState.persons[1] = p2;

当我这样做时,我得到总线错误(核心转储)。当我只设置人员时,一切正常。 IE。这行得通:

int num_walls = 0;
int num_preson = 2;

State simState = *(State*)malloc( sizeof(simState) + num_person*sizeof(Person) + num_walls*sizeof(Wall));
simState.num_walls = num_walls;
simState.num_persons = num_person;
// simState.walls[0] = w;
simState.persons[0] = p1;
simState.persons[1] = p2;

代码是c++11,我用的是gcc (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609

为什么会这样?

【问题讨论】:

您的struct State 定义不正确,无法编译。请提供您的实际代码。 这是不合法的 C++ Wall walls[]; @john 也不是合法的 C,因为不在 struct 的末尾。 OP:请仅标记您打算使用的语言。 C C++。目前,代码不应以两种语言中的任何一种进行编译。 @FerdiK 请形成一个完整的minimal reproducible example 并告诉我们您正在使用哪个编译器来编译它,因为它不应该编译。 澄清一下,您使用的 GCC 版本确实可以编译代码。但是在 C++ 中不允许将具有未知边界的数组作为 struct 成员,而在 C 中它们只允许在结构的末尾(所谓的“灵活数组成员”)。 GCC 允许它在结构中的其他位置似乎是一个错误,自 GCC 6 以来似乎已修复。使用 -pedantic-errors 标志强制 GCC 为此类在 C++ 中实际上不允许并且只是特定于编译器的扩展。 【参考方案1】:

所以这是合法的 C++,它可能是你想要实现的目标

struct State 
    int num_walls;
    Wall* walls;
    int num_persons;
    Person* persons;
;

State simState;
simState.num_walls = num_walls;
simState.walls = new Wall[num_walls];
simState.num_persons = num_person;
simState.persons = new Person[num_person];
simState.walls[0] = w;
simState.persons[0] = p1;
simState.persons[1] = p2;

这不是好的 C++,但至少它是合法的。

重要的一点(在任何一种语言中)是您不必分配simState,它只需通过声明即可获得内存,但您必须分配两个可变长度数组simState.personssimState.walls

【讨论】:

给我一个段错误。 @FerdiK 好吧,您在其他地方有一个错误,如果没有看到更多代码,就不可能说出在哪里。【参考方案2】:

不允许在 C++ 中定义无量纲数组,您应该使用其他人所说的带有分配(new 甚至 malloc)的指针。

无量纲数组是 C99 中的有效构造,它不称为 VLA,而是 flexible array member。语言的这一特性只能用作结构的最后一个成员,并在定义和使用方面有一些其他限制。绝对不是经常使用的功能。

第一个示例中“总线错误”的原因是 wall 的非法定义,它不是结构的最后一个成员。由于 person 定义正确,因此您正在访问过去结构的内存并覆盖其他实际上不是您想要做的事情。 GCC 是您的程序即使在无效时也能编译的原因,因为默认情况下启用了许多扩展。请结合使用 -pedantic 标志和 C++ 标准版本 (-std=c++11) 来获得警告。

【讨论】:

以上是关于在结构中设置数组元素时出现总线错误的主要内容,如果未能解决你的问题,请参考以下文章

在supervisord中设置环境变量时出现Python键错误

尝试在 lambda 函数中设置按钮标签时出现分段错误

在 .htaccess 中设置 php_value 时出现意外错误?

在 asp .net CORE / MVC 6 应用程序中设置 Swagger 时出现 500 错误

在 Java 对象的 Kotlin 中设置属性时出现奇怪的“无法重新分配 Val”错误

在 Java 对象的 Kotlin 中设置属性时出现奇怪的“无法重新分配 Val”错误