在结构体中初始化类对象触发段错误的技术求助
终端彩色文本输出程序的段错误问题解决
问题描述
我正在编写一个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++是为了通过类和方法灵活控制字符颜色,避免硬编码字符串。
错误分析与修复
核心错误点
- 宏定义语法错误:
#define COLOR_PREPEND 0x001b;末尾多了分号,导致赋值时出现冗余语句;更关键的是,将0x001b强制转为char*是把数值当作内存地址使用,这个地址属于无效内存,sprintf读取时直接触发段错误。 - 字符串传递逻辑错误:
%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
相关产品推荐
相关产品推荐

