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

GCC中结合C++20模块使用std::string拼接触发段错误问题

问题原因与修复方案

问题现象

使用g++ 12.2.1编译代码无错误,但运行时触发Segmentation fault (core dumped);移除构造函数初始化列表中的三条字符串初始化语句后,错误消失。

相关代码如下:

主程序test_main.cpp

import shared_buffer;

namespace sb = shared_buffer;

struct DataRecord {
    int i;
};

int main () {
    sb::Handle <DataRecord, 10> handle ("my_handle");
    return 0;
}

模块shared_buffer.cpp

export module shared_buffer;

import <string>;
import <iostream>;

namespace st = std;

export namespace shared_buffer {

template <typename Record, int maxNrOfRecords>
struct Content {
    int size = 0;
    Record records [maxNrOfRecords];
};

template <typename Record, int maxNrOfRecords>
class Handle {
public:
    st::string name;
    st::string mutexName ;
    st::string memoryName;
    Content <Record, maxNrOfRecords> content;

    Handle (st::string name):
        // 添加这3行触发段错误
        name (name),
        mutexName (name + "_mutex"),
        memoryName (name + "_memory")
    {
        st::cout << name << '\n';
        st::cout << mutexName << '\n';
        st::cout << memoryName << '\n';
    }
};

}

编译脚本compile

clear
g++ -std=c++20 -fmodules-ts -xc++-system-header string
g++ -std=c++20 -fmodules-ts -xc++-system-header iostream
g++ -std=c++20 -fmodules-ts shared_buffer.cpp test_main.cpp

问题原因

构造函数的参数名name与类成员变量name重名,在初始化列表中:

  • name(name)会被编译器解析为用未初始化的成员变量name初始化自身,此时成员变量还未完成构造,处于非法内存状态。
  • 后续mutexName (name + "_mutex")和memoryName (name + "_memory")中的name,访问的是未初始化的成员变量而非构造函数参数,对未初始化的std::string执行拼接操作属于未定义行为,直接触发段错误。

修复方案

修改构造函数的参数名,避免与成员变量重名,比如将参数改为_name,再用参数初始化成员:

修改后的Handle类构造函数部分:

Handle (st::string _name):
    name (_name),
    mutexName (_name + "_mutex"),
    memoryName (_name + "_memory")
{
    st::cout << name << '\n';
    st::cout << mutexName << '\n';
    st::cout << memoryName << '\n';
}

也可以通过this->name明确指定成员变量,用参数初始化(推荐结合std::move减少拷贝):

Handle (st::string name):
    name (std::move(name)),
    mutexName (this->name + "_mutex"),
    memoryName (this->name + "_memory")
{
    st::cout << name << '\n';
    st::cout << mutexName << '\n';
    st::cout << memoryName << '\n';
}

前者代码更直观,能从根源避免命名歧义,是更推荐的写法。


内容的提问来源于stack exchange,提问作者Jacques de Hooge

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 22:28:25