You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fedora39下GCC编译C++代码出现Segmentation fault的原因排查

C++代码出现Segmentation fault的原因分析

我在Fedora 39系统上使用gnu编译器g++ (GCC) 13.2.1 20231205 (Red Hat 13.2.1-6)运行以下C++代码时,出现了Segmentation fault (core dumped)错误:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main (int argc, char** argv)
{
    string stri = "";
    cout << "Enter some characters: ";
    getline(cin, stri);
    cout << "You entered: " << stri << endl;
    clog << "This is the output to a terminal \"clog\"! " << stri << endl;
    ofstream out ("clog.txt");
    if (out) {
        clog.rdbuf(out.rdbuf());
    }
    else
    {
        cerr << "This is the output to a terminal \"cerr\"" << stri << endl; 
    }
    clog << "This is the output to a file \"clog\"! " << stri << endl; 
    
    return 0;
}

运行输出:

Enter some characters: re
You entered: re
This is the output to a terminal "clog"! re
Segmentation fault (core dumped)

但仅添加一个未使用的string变量stri1后,代码即可正常运行:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main (int argc, char** argv)
{
    string stri = "";
    string stri1 = ""; // 仅添加此未使用变量就不再报错
    cout << "Enter some characters: ";
    getline(cin, stri);
    cout << "You entered: " << stri << endl;
    clog << "This is the output to a terminal \"clog\"! " << stri << endl;
    ofstream out ("clog.txt");
    if (out) {
        clog.rdbuf(out.rdbuf());
    }
    else
    {
        cerr << "This is the output to a terminal \"cerr\"" << stri << endl;
    }
    clog << "This is the output to a file \"clog\"! " << stri << endl; 
    
    return 0;
}

运行输出:

Enter some characters: re
You entered: re
This is the output to a terminal "clog"! re

两种情况均能正确将信息写入clog.txt文件,以下是问题原因分析:


问题根源

核心问题是**clog的缓冲区生命周期与局部变量out的生命周期冲突**:

  • std::clog默认使用全局标准错误流的缓冲区(和std::cerr共享)。当调用clog.rdbuf(out.rdbuf())时,clog会接管out的文件缓冲区,但未保存原缓冲区指针。
  • 函数main执行完毕时,局部变量out会被销毁,其内部的文件缓冲区内存也会被释放。但此时std::clog仍然指向这块已被释放的内存。
  • 程序退出阶段,C++标准库会尝试刷新并销毁std::clog的缓冲区,访问已释放内存直接触发Segmentation fault。

为什么添加stri1能"解决"问题?

这是栈内存布局变化导致的巧合,属于C++未定义行为的表现:

  • 添加stri1后,栈上的内存布局被改变。当out销毁时,其原缓冲区所在的内存可能未被立即覆盖或回收,程序退出时的内存检查恰好没触发错误。
  • 这不是真正的解决方案,只是错误被暂时隐藏,换个环境或输入仍可能复现崩溃。

正确的修复方式

要避免问题,需在替换缓冲区时保存原指针,并在out销毁前恢复clog的原缓冲区:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char** argv)
{
    string stri = "";
    cout << "Enter some characters: ";
    getline(cin, stri);
    cout << "You entered: " << stri << endl;
    clog << "This is the output to a terminal \"clog\"! " << stri << endl;
    
    ofstream out("clog.txt");
    if (out) {
        // 保存clog的原缓冲区指针
        streambuf* original_buf = clog.rdbuf(out.rdbuf());
        clog << "This is the output to a file \"clog\"! " << stri << endl;
        // 恢复clog的原缓冲区
        clog.rdbuf(original_buf);
    } else {
        cerr << "This is the output to a terminal \"cerr\"" << stri << endl;
    }
    
    return 0;
}

这样clog在out销毁前就恢复了原缓冲区,程序退出时不会访问已释放的内存。

内容的提问来源于stack exchange,提问作者questioner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:02:45