为何C语言代码报错0xC0000005,加无关printf却能部分运行?
问题:C语言面向对象String结构体运行时出现0xC0000005错误
刚接触C语言,我实现了一个面向对象风格的String结构体,运行时弹出错误:Process finished with exit code -1073741819 (0xC0000005),问题似乎出在set函数里。
在set函数中加了一条无关的printf("Debug")后,控制台能输出DebugHello,但还是会报同样的错误。
相关代码
头文件(mystring.h)
#include <string.h> #include <stdbool.h> typedef struct String_Struct { char* value; unsigned int length; void (*set) (struct String_Struct* self, char* value); bool (*equals) (const struct String_Struct* self, const struct String_Struct* other); int (*compareTo) (const struct String_Struct* self, const struct String_Struct* other); void (*concat) (struct String_Struct* self, const struct String_Struct* other); void (*freeString) (struct String_Struct* self); } String; String* newString (char* value); void set (String* self, char* value); bool equals (const String* self, const String* other); int compareTo (const String* self, const String* other); void concat (String* self, const String* other); void freeString (String* self);
实现文件(mystring.c)
#include "mystring.h" #include <stdlib.h> #include <stdio.h> void set (String* self, char* value) { // Only proceed if self and value exist if (!self || !value) { return; } free(self->value); self->length = strlen(value) + 1; self->value = (char*) malloc(sizeof(char) * self->length); strcpy(self->value, value); } int compareTo (const String* self, const String* other) { if ((!self && other) || (self && !other)) return INT_MIN; return strcmp(self->value, other->value); } bool equals (const String* self, const String* other) { if ((!self && other) || (self && !other)) return false; if (self == other) return true; return strcmp(self->value, other->value) == 0; } void concat (String* self, const String* other) { if (!self || !other) { return; } char* result = (char*) malloc(sizeof(char) * (strlen(self->value) + strlen(other->value) + 2)); strcpy(result, self->value); strcat(result, other->value); self->set(self, result); } void freeString (String* self) { free(self->value); free(self); } String* newString (char* value) { String* str = (String*) malloc(sizeof(String)); str->set = &set; str->equals = = str->compareTo = &compareTo; str->concat = &concat; str->freeString = &freeString; str->set(str, value); return str; }
main.c
#include <stdio.h> #include "mystring.h" int main() { String* string = newString("Hello"); printf("%s", string->value); return 0; }
错误原因与修复方案
核心错误:野指针非法free
在newString函数中,用malloc分配String结构体内存后,str->value是未初始化的野指针。第一次调用set函数时,free(self->value)相当于释放一块不属于你的内存,直接触发了0xC0000005内存访问违规错误。
加printf后能输出是因为内存布局巧合,野指针暂时没触发致命崩溃,但本质问题没解决。
修复步骤
- 初始化
value为NULL
在newString中分配结构体后,先把str->value设为NULL,标准C中free(NULL)是安全操作,不会触发错误:
String* newString (char* value) { String* str = (String*) malloc(sizeof(String)); str->value = NULL; // 关键:初始化空指针 str->set = &set; str->equals = = str->compareTo = &compareTo; str->concat = &concat; str->freeString = &freeString; str->set(str, value); return str; }
- 修复concat中的内存泄漏
concat里用malloc创建的result,在调用set后没有释放,会导致内存泄漏,需要手动free:
void concat (String* self, const String* other) { if (!self || !other) { return; } char* result = (char*) malloc(sizeof(char) * (strlen(self->value) + strlen(other->value) + 2)); strcpy(result, self->value); strcat(result, other->value); self->set(self, result); free(result); // 释放临时内存 }
- main函数中释放String对象
程序结束前记得调用freeString释放内存,避免泄漏:
int main() { String* string = newString("Hello"); printf("%s", string->value); string->freeString(string); // 释放对象 return 0; }
额外注意点
compareTo中使用INT_MIN需要包含<limits.h>头文件,否则会编译报错;- C语言中
malloc的返回值不需要强制转换(C++才需要),可以去掉(char*)这类转换让代码更简洁。
内容的提问来源于stack exchange,提问作者Anton Sch9nfeld
相关产品推荐
相关产品推荐

