C语言第二次调用strcpy()时程序崩溃问题排查
问题核心原因
代码中声明的Hashtable_Entry_t*类型指针student、student2均为野指针:声明指针变量时,既没有为其指向的结构体实例分配合法内存,也没有给指针赋值有效的内存地址,指针存储的是栈空间残留的随机垃圾值。此时直接通过->解引用指针访问、修改成员的操作属于C语言标准定义的未定义行为,程序运行结果不受任何保证,出现部分代码执行成功、后续直接崩溃的现象完全符合这类错误的典型特征。
为什么第一次操作student没有立刻崩溃,第二次操作student2才终止:
- 未定义行为不会保证每次都立刻触发崩溃:第一次操作
student时,指针里的随机值刚好落在进程可访问、可写入的内存范围内,写入操作没有触发操作系统的内存保护机制,因此对应的printf可以正常输出——但这时候代码已经在非法篡改不属于该变量的内存,只是没有立刻触发显性错误而已。 - 到操作
student2时,指针存储的随机值指向了受系统保护的不可写内存区域,执行strcpy往该地址写入数据时直接触发段错误(Segmentation Fault),操作系统会强制终止进程,后续的printf语句根本没有执行机会。
另外你代码里strcpy前后的两个打印语句都写的是Before 2nd strcpy.,属于笔误,修复内存问题后可以改成对应提示避免误导。
修复方案
只要保证指针指向合法分配的结构体内存即可,两种常见实现方式:
- 方式1:直接声明栈上的结构体实例,不需要手动管理内存
int main(int argc, char const *argv[]) { // 直接声明结构体变量,栈上自动分配合法内存 Hashtable_Entry_t student; strcpy(student.matrikelnr, "70468878"); student.note = 1.0; printf("%s, %.1f\n", student.matrikelnr, student.note); Hashtable_Entry_t student2; printf("Before 2nd strcpy.\n"); strcpy(student2.matrikelnr, "70468878"); printf("After 2nd strcpy.\n"); student2.note = 1.0; printf("%s, %.1f", student2.matrikelnr, student2.note); return 0; }
- 方式2:如果必须使用指针,通过
malloc申请堆内存,使用完成后手动释放
#include <stdlib.h> // 引入内存分配函数的头文件 int main(int argc, char const *argv[]) { Hashtable_Entry_t* student = malloc(sizeof(Hashtable_Entry_t)); if (student == NULL) return 1; // 处理内存申请失败的异常 strcpy(student->matrikelnr, "70468878"); student->note = 1.0; printf("%s, %.1f\n", student->matrikelnr, student->note); free(student); // 用完释放内存避免泄漏 Hashtable_Entry_t* student2 = malloc(sizeof(Hashtable_Entry_t)); if (student2 == NULL) return 1; printf("Before 2nd strcpy.\n"); strcpy(student2->matrikelnr, "70468878"); printf("After 2nd strcpy.\n"); student2->note = 1.0; printf("%s, %.1f", student2->matrikelnr, student2->note); free(student2); return 0; }
内容的提问来源于stack exchange,提问作者J.Fasterling
相关产品推荐
相关产品推荐

