Cygwin栈转储错误求助:打印Company结构体时程序崩溃
问题描述
我正在开发一个项目,需要打印搜索到的结构体,但执行打印操作时,仅完成首次输出程序就退出,并抛出错误:cygwin_exception::open_stackdumpfile: Dumping stack trace。我查询得知该错误通常与动态内存问题相关,但据我所知,我仅读取并打印已有数据,未进行内存新增操作,因此疑惑为何出现该问题。即使手动指定打印结构体内容,仍出现相同错误。
打印函数
void printCompany(Companies companies, int i) { printf("\nNif: %d", companies.companies[i].Nif); printf("\nName: %s", companies.companies[i].name); printf("\nCategory: %s", companies.companies[i].categories); }
结构体定义
#define COMPANY_INITIAL_SIZE 20 #define SEARCHES_INITIAL_SIZE 20 #define ACTIVITIES_INITIAL_SIZE 20 #define TEXT_MAX_SIZE 200 #define NAME_MAX_SIZE 50 #define EMAIL_MAX_SIZE 50 #define TITLE_MAX_SIZE 50 #define STREET_MAX_SIZE 70 #define LOCATION_MAX_SIZE 70 #define NIF_MIN_SIZE 100000000 #define NIF_MAX_SIZE 999999999 enum category { microCompany = 1, pmeCompany, macroCompany }; enum state { inactive, active }; enum searchCamp { nif, businessArea, nameLocation }; typedef struct { char title[TITLE_MAX_SIZE]; char text[TEXT_MAX_SIZE]; char userName[NAME_MAX_SIZE]; char userEmail[EMAIL_MAX_SIZE]; } Coment; typedef struct { int nota; char userName[NAME_MAX_SIZE]; char userEmail[EMAIL_MAX_SIZE]; } Rating; typedef struct { int Nif; char name[NAME_MAX_SIZE]; enum category categories; int businessAreaCode; enum state states; char street[STREET_MAX_SIZE]; char location[LOCATION_MAX_SIZE]; int postalCode; int nComents; Coment coments; int nRating; Rating ratings; } Company; typedef struct { int counter, size; Company *companies; } Companies; void freeCompanies(Companies *); void loadCompanyFile(Companies *, char*); void saveCompanyFile(Companies *, char *); void insertCompanies(Companies*); void expandCompanySize(Companies *); void searchNifCompanies(Companies); //void printCompany(Company); void printCompany(Companies,int);
调用打印函数的相关函数
/** * @brief 查找匹配NIF的公司 * @param companies Companies结构体 * @param nif 公司唯一NIF值 * @return 成功则返回公司索引,失败返回-1 */ int searchNifCompany(Companies companies, int nif) { int i; for (i = 0; i < companies.counter; i++) { if (companies.companies[i].Nif == nif) { return i; } } return -1; } /** * @brief 处理NIF搜索逻辑 * @param companies Companies结构体 * @return */ void searchNifCompanies(Companies companies) { int company, nif; nif = getInt(NIF_MIN_SIZE, NIF_MAX_SIZE, "\nNIF[9 digits]: "); company = searchNifCompany(companies, nif); if (company != -1) { //printCompany(companies.companies[company]); printCompany(companies, company); } else { puts("该公司不存在。"); } }
手动打印结构体的代码
Companies companies; int main() { loadCompanyFile(&companies, COMPANIES_FILE_NAME); mainMenu(); printf("\nNif: %d", companies.companies[1].Nif); printf("\nName: %s", companies.companies[1].name); printf("\nCategory: %s", companies.companies[1].categories); saveCompanyFile(&companies, COMPANIES_FILE_NAME); freeCompanies(&companies); return (EXIT_SUCCESS); }
问题根源与解决方法
核心错误:枚举类型用字符串格式符输出
打印代码中这一行是直接触发错误的原因:
printf("\nCategory: %s", companies.companies[i].categories);
categories是enum category类型,本质是整数,但你用了%s(字符串格式符),printf会把枚举的整数值当成内存地址去读取字符串,直接访问非法内存,触发段错误,也就是你看到的cygwin栈转储。
修复方式
给枚举值做字符串映射,新增一个辅助函数:
const char* getCategoryName(enum category cat) { switch(cat) { case microCompany: return "微型企业"; case pmeCompany: return "中小企业"; case macroCompany: return "大型企业"; default: return "未知类型"; } }
然后修改打印函数:
void printCompany(Companies companies, int i) { printf("\nNif: %d", companies.companies[i].Nif); printf("\nName: %s", companies.companies[i].name); printf("\nCategory: %s", getCategoryName(companies.companies[i].categories)); }
其他潜在问题修复
- 结构体传值的副本隐患:
searchNifCompanies和searchNifCompany都传结构体值,会生成副本,若原结构体的堆内存被释放,副本指针会变成野指针。建议改成传指针:
int searchNifCompany(Companies *companies, int nif) { int i; for (i = 0; i < companies->counter; i++) { if (companies->companies[i].Nif == nif) { return i; } } return -1; } void searchNifCompanies(Companies *companies) { int company, nif; nif = getInt(NIF_MIN_SIZE, NIF_MAX_SIZE, "\nNIF[9 digits]: "); company = searchNifCompany(companies, nif); if (company != -1) { printCompany(*companies, company); } else { puts("该公司不存在。"); } }
- 数组越界检查:手动打印
companies.companies[1]时,要确保companies.counter > 1,避免访问超出数组范围的内存:
if (companies.counter > 1) { printf("\nNif: %d", companies.companies[1].Nif); printf("\nName: %s", companies.companies[1].name); printf("\nCategory: %s", getCategoryName(companies.companies[1].categories)); } else { puts("没有足够的公司数据。"); }
内容的提问来源于stack exchange,提问作者bnnnas 12
相关产品推荐
相关产品推荐

