C++ pragma pack(push)没有相应的pop导致堆栈崩溃

C++ pragma pack(push)没有相应的pop导致堆栈崩溃,c++,segmentation-fault,stack-smash,pragma-pack,C++,Segmentation Fault,Stack Smash,Pragma Pack,我在头文件的结构开头使用了#pragma pack(push,2),但忘记了相应的#pragma pack(pop)。在包含这个头文件之后,我包含了fstream。在创建流的对象时,我看到堆栈崩溃。具体场景和代码的详细信息如下 我是在遵循C++课程并编写了一个项目代码。我的程序因堆栈崩溃而崩溃。我试图查找任何明显的溢出错误,但找不到任何错误。我修改了几乎所有的代码,使之类似于讲师提供的代码。唯一的区别是包含的头文件的顺序。我在头文件后面加了fstream,而讲师在顶部加了fstream头文件。但

我在头文件的结构开头使用了
#pragma pack(push,2)
,但忘记了相应的
#pragma pack(pop)
。在包含这个头文件之后,我包含了fstream。在创建流的
对象时,我看到堆栈崩溃。具体场景和代码的详细信息如下

我是在遵循C++课程并编写了一个项目代码。我的程序因堆栈崩溃而崩溃。我试图查找任何明显的溢出错误,但找不到任何错误。我修改了几乎所有的代码,使之类似于讲师提供的代码。唯一的区别是包含的头文件的顺序。我在头文件后面加了
fstream
,而讲师在顶部加了
fstream
头文件。但我还是遇到了同样的问题。所以我甚至改变了头文件的顺序,瞧,问题消失了

由于这对我来说很奇怪,我试图在代码中对问题进行本地化。
我在代码中插入了print语句,以查找发生堆栈崩溃的函数

在找到函数时,我使用gdb设置watch,以查看我的程序用于检查堆栈崩溃的金丝雀值。我在stream
对象的
构造函数中检测到堆栈崩溃

此时,我知道在
fstream
之前包含的一些头文件正在干扰它。因此,现在我检查了所有头文件是否有任何愚蠢的错误,发现一个结构前面有
#pragma pack(push,2)
,后面没有相应的
#pragma pack(pop)
。此结构将作为二进制文件写入。纠正这一点解决了问题

因为整个项目都是无关的,所以我用一个简单的代码片段重现了这个问题。虽然问题解决了,但我想知道为什么会发生。我知道,
pragma pack
指令用于防止编译器在结构中插入填充,因为结构必须写入二进制文件。省略结构末尾的
pack(pop)
,对所有后续头文件使用相同的方法。但这是否会导致流构造函数写入堆栈帧

我在Ubuntu 18.04上使用gcc v7.4.0

/* code.cpp */ 
#include "header.h"
#include <fstream>
using namespace std;

int main(){
    ofstream fout;
    fout.open("file.ext", ios::out|ios::binary);
    fout.close();
    return 0;
}

由于
pragma-pack
会影响类实例的布局,因此流的
版本与编译标准库时使用的版本不一样。在形式上,您有一个ODR冲突,这将导致未定义的行为


实践中,C++运行时的函数在错误布局的数据上盲目操作,所以焰火随之而来是有意义的。由于打包的类比未打包的类短,因此特别需要堆栈崩溃,因此写入实例末尾会溢出为其保留的空间
main

因此,当我使用pragma pack(push,2)时,我的结构和类(在fstream中)当库代码尝试在填充有空白的结构中写入时,将以2字节对齐。因此,它最终会在堆栈框架上进行写入。如果我的理解是错误的,请纠正我。@vkj就是这样。
#ifndef HEADER_H_
#define HEADER_H_

#pragma pack(push, 2)
struct something{
    int a;
};
//#pragma pack(pop)
//Uncommenting the above line solves the problem

#endif