Valgrind提示向struct成员拷贝字符串存在重叠问题如何解决
问题根因
你的代码核心错误是混淆了指针本身的存储地址和指针指向的内存地址的操作逻辑:
- 结构体中的
file_name是char*类型的未初始化指针,本身没有指向合法的可写内存。你直接对&threads[length].file_name(即指针本身的存储地址)执行memmove,本质是在篡改指针本身的存储值,而非往指针指向的内存写入字符串内容。如果字符串长度超过指针本身的字节数(64位系统下指针占8字节),还会直接发生内存越界,属于严重的未定义行为。 - 经过错误的
memmove赋值后,file_name指针被篡改后的地址刚好和argv[index]指向的地址相同,后续调用strcpy时源地址和目标地址完全一致,因此Valgrind会抛出内存重叠的报错。你之前用memcpy时打印结果正常只是未定义行为的巧合,实际上代码一直存在内存安全隐患。
解决方案
根据使用场景二选一即可:
方案1:直接复用命令行参数内存
命令行参数argv指向的字符串在程序整个运行生命周期内都不会被释放,如果你不需要单独修改file_name的内容,直接赋值指针即可,不需要任何内存拷贝操作:
for (int index = optind; index < argc; index++) { threads[length].rb = rb; threads[length].file_name = argv[index]; ++length; }
方案2:独立拷贝字符串
如果后续需要自由修改file_name的内容且不影响原argv,可以用strdup完成内存分配+字符串拷贝,也可以手动malloc后拷贝:
// 方式一:用strdup实现,后续不用时要调用free(threads[xxx].file_name)释放内存 for (int index = optind; index < argc; index++) { threads[length].rb = rb; threads[length].file_name = strdup(argv[index]); // 生产环境建议增加判空,处理内存分配失败的逻辑 ++length; } // 方式二:手动malloc+strcpy实现,逻辑和strdup等价 for (int index = optind; index < argc; index++) { threads[length].rb = rb; size_t str_len = strlen(argv[index]) + 1; // +1 用于存储字符串结尾的'\0' threads[length].file_name = malloc(str_len); if (threads[length].file_name == NULL) { perror("内存分配失败"); exit(EXIT_FAILURE); } strcpy(threads[length].file_name, argv[index]); ++length; }
内容的提问来源于stack exchange,提问作者Pochetes
相关产品推荐
相关产品推荐

