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

在结构体中初始化类对象触发段错误的技术求助

终端彩色文本输出程序的段错误问题解决

问题描述

我正在编写一个C++程序,用于在终端输出不同颜色的文本,现有代码如下:

#include <ctype.h>
#include <stdio.h>
#include <unistd.h>

// Works on little endian processors which mine happens to be
#define COLOR_PREPEND 0x001b;

class Color
{
private:
    char contents[6];
public:
    Color() {
        short prepend = COLOR_PREPEND;
        sprintf(contents, "%s[%dm", (char *)prepend, 0);
    }
    Color(int code) {
        short prepend = COLOR_PREPEND;
        sprintf(contents, "%s[%dm", (char *)prepend, code);
    }
};

typedef struct {
    Color *set;
    char c;
    Color *reset;
} letter_template;

letter_template essay[100];

int main() {
    // Initialize array
    for (int i = 0; i < sizeof(essay)/sizeof(essay[0]); i++) {
        essay[i].set = new Color(); essay[i].reset = new Color();
    }

    return 0;
}

程序在for循环首次迭代时触发段错误,调试发现essay数组中所有元素的set和reset属性均为null值,无法初始化Color对象。

原本我希望实现按「颜色序列>字符>颜色序列」循环的连续字符串,目前的代码虽未完全达成该目标,但我无法理解为何初始化逻辑无法运行。此前该sprintf逻辑在main函数中单独运行正常,且contents数组的6字节空间足够容纳生成的内容。

补充说明:已补充完整代码及头文件,编译命令为g++ -c main.cpp -o main.o; g++ main.o -o main.exe,问题依旧。代码原为C语言编写,改用C++是为了通过类和方法灵活控制字符颜色,避免硬编码字符串。

错误分析与修复

核心错误点

  1. 宏定义语法错误:#define COLOR_PREPEND 0x001b;末尾多了分号,导致赋值时出现冗余语句;更关键的是,将0x001b强制转为char*是把数值当作内存地址使用,这个地址属于无效内存,sprintf读取时直接触发段错误。
  2. 字符串传递逻辑错误:%s格式符需要接收以\0结尾的字符串指针,而你试图用单个ESC字符的数值冒充指针,完全不符合sprintf的参数要求。

修复后的完整代码

#include <stdio.h>
#include <unistd.h>

// 定义终端颜色控制的ESC字符(ASCII 27)
#define COLOR_ESC '\033'

class Color
{
private:
    char contents[6];
public:
    Color() {
        // 使用snprintf避免缓冲区溢出,直接嵌入ESC字符生成控制序列
        snprintf(contents, sizeof(contents), "%c[%dm", COLOR_ESC, 0);
    }
    Color(int code) {
        snprintf(contents, sizeof(contents), "%c[%dm", COLOR_ESC, code);
    }
    // 提供对外访问控制字符串的接口
    const char* get() const {
        return contents;
    }
};

typedef struct {
    Color *set;
    char c;
    Color *reset;
} letter_template;

letter_template essay[100];

int main() {
    // 初始化数组
    for (int i = 0; i < sizeof(essay)/sizeof(essay[0]); i++) {
        essay[i].set = new Color(); 
        essay[i].reset = new Color();
    }

    // 测试输出一个红色字符(31是红色前景色代码)
    essay[0].set = new Color(31);
    essay[0].c = 'A';
    printf("%s%c%s\n", essay[0].set->get(), essay[0].c, essay[0].reset->get());

    // 释放堆内存,避免泄漏
    for (int i = 0; i < sizeof(essay)/sizeof(essay[0]); i++) {
        delete essay[i].set;
        delete essay[i].reset;
    }

    return 0;
}

额外优化说明

  • 用snprintf替代sprintf:严格限制写入缓冲区的字节数,避免因颜色代码位数过多导致缓冲区溢出。
  • 新增get()方法:原代码中contents是私有成员,外部无法访问,新增方法后才能正常获取颜色控制字符串。
  • 补充内存释放逻辑:避免大量new创建的Color对象导致堆内存泄漏。
  • 移除无用头文件:<ctype.h>未被使用,直接删除以精简代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:15:56