C语言多线程场景下char数组入队列后值丢失的解决方法
问题分析与解决方案
问题根源
你代码里的buffer是栈局部变量,当接收消息的代码块执行完毕后,栈帧会被销毁,这块内存会被后续函数调用覆盖。你直接把item->path = buffer,只是将栈内存的地址存入item,并没有复制实际的字符串内容,所以worker线程读取时,原内存的数据已经丢失。而硬编码的字符串字面量存在进程只读数据段,不会被销毁,所以能正常打印。
修正后的接收消息代码
size_t received_bytes = 0; char buffer[MAX_CACHE_REQUEST_LEN]; received_bytes = 0; memset(buffer, 0, MAX_CACHE_REQUEST_LEN); received_bytes = mq_receive(mq, buffer, MAX_CACHE_REQUEST_LEN, NULL); if (received_bytes != -1) { item_type *item = malloc(sizeof(item_type)); // 为路径字符串分配堆内存,预留字符串结束符位置 item->path = malloc(received_bytes + 1); if (item->path == NULL) { free(item); continue; } // 拷贝接收的内容到堆内存 strncpy(item->path, buffer, received_bytes); item->path[received_bytes] = '\0'; // 确保字符串以'\0'结尾 pthread_mutex_lock(&queue_lock); steque_enqueue(&queue, item); pthread_cond_signal(&queue_cond); pthread_mutex_unlock(&queue_lock); }
修正后的worker线程代码
void *worker(void *arg) { item_type *new_item; char *path; int fd; while (1) { pthread_mutex_lock(&queue_lock); while (steque_isempty(&queue) == 1) pthread_cond_wait(&queue_cond, &queue_lock); new_item = steque_pop(&queue); path = new_item->path; pthread_mutex_unlock(&queue_lock); // 提前解锁,避免锁持有时间过长 fd = simplecache_get(path); sleep(cache_delay); printf("%d\n", fd); printf("%s\n", path); // 业务逻辑处理 if (fd == CACHE_FAILURE) { } else { } // 释放堆内存,避免泄漏 free(path); free(new_item); new_item = NULL; path = NULL; } }
关键注意事项
- 必须为
item->path分配堆内存并拷贝内容,不能直接复用栈内存地址 - 内存分配失败时要做容错处理,避免内存泄漏
- worker线程中完成队列操作后立即解锁,不要持有锁执行耗时操作(如sleep、缓存查询),提升并发性能
- 确保接收的消息是字符串格式,若为二进制数据需调整拷贝逻辑
内容的提问来源于stack exchange,提问作者Josh Voytek
相关产品推荐
相关产品推荐

