You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何向pthread_exit()传递void*返回值时一种方式结果异常?

问题背景

初次学习POSIX线程编程时,测试两种向pthread_exit()传递void*类型返回值的写法,发现仅一种写法可以得到预期结果,复现场景如下。

复现代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h> 
#include <string.h>

static void *threadFunction(void *arg)
{
  printf("thread1: hello from thread...\n");
  char array_of_chars[] = "goodbye...";
  char *ptr_to_first_element_in_array_of_chars = array_of_chars;
  
  void *exitStatus_ptr;
  exitStatus_ptr = ptr_to_first_element_in_array_of_chars;

  printf("thread1: thread about to die...\n");
  //pthread_exit( exitStatus_ptr ); /** denote as Line 17 **/
  pthread_exit((void *) "goodbye..."); /** denote as Line 18 **/
}
int main(int argc, int *argv[]) //main thread
{

  pthread_t thread1;

  void *targetThread_exitStatus;
  int s; 

  s = pthread_create(&thread1, NULL, threadFunction, NULL); 

  if (s != 0) 
  {
    perror("pthread_create() error...");
  }
  
  s = pthread_join(thread1, &targetThread_exitStatus);
  
  if (s != 0)
  {
    perror("pthread_join() error...");
  }

  printf("main thread: retval from thread is: %s\n", (char*) targetThread_exitStatus);
  printf("main thread: thread about to die...\n");

  pthread_exit(NULL);

} 

复现操作与现象

在Linux终端执行编译命令:
gcc code.c -lpthread -o code
编译完成后运行./code,两种写法的运行表现存在明显差异:

  • 启用标注为Line18的pthread_exit((void *) "goodbye...");语句、注释Line17时,运行结果符合预期,主线程可正确打印线程返回的字符串"goodbye..."
  • 注释Line18、启用标注为Line17的pthread_exit( exitStatus_ptr );语句时,主线程无法打印出正确的返回字符串内容。

这里存在一个明显的疑问:C语言中字符串以字符数组形式存储,数组名会退化为指向首元素的指针,为何两种传参方式仅有一种可得到预期结果?

原因解析

两种写法的核心差异是传给pthread_exit的指针指向的内存生命周期完全不同,和数组退化规则没有关系。

  1. Line18写法生效的原因
    代码中的"goodbye..."是字符串字面量,程序编译时这类内容会被存放到进程的只读数据段,内存生命周期覆盖程序整个运行周期,不会因为线程退出、函数返回被回收或覆写。pthread_exit传递的指针指向这块永久合法的内存,主线程调用pthread_join拿到指针时,内存内容依然完整有效,因此可以正常打印字符串。
  2. Line17写法失效的原因
    线程函数内定义的char array_of_chars[] = "goodbye...";是分配在线程栈上的局部数组,内存生命周期仅在threadFunction函数执行期间有效。当线程调用pthread_exit退出、线程函数执行结束后,这块栈内存会被系统回收,后续随时可能被其他操作覆写内容。
    此时传给pthread_exit的exitStatus_ptr是指向已回收栈内存的野指针,主线程拿到指针后读取内存时,原位置存储的字符串早就被破坏,自然无法打印出正确内容。

注意:数组退化为指针仅代表指针的值(内存地址)和数组首元素地址一致,不代表指针指向的内存会一直保持有效。只要指向的内存生命周期结束,无论指针值本身看起来多么“正确”,解引用操作都属于未定义行为,结果不可预期。

线程返回字符串的正确实现方式

如果需要通过pthread_exit返回字符串,可以选择以下几种合法写法:

  • 直接返回字符串字面量(即Line18的写法,注意不要尝试修改字面量内容,否则会触发段错误)
  • 在线程函数内调用malloc从堆上分配内存存储字符串,将堆指针作为返回值传递,主线程拿到指针使用完成后需要调用free释放内存,避免内存泄漏
  • 将待返回的内容存储到全局变量、或者主线程通过线程参数传入的合法内存块中,保证这块内存在pthread_join执行完成前不会被释放或覆写

内容的提问来源于stack exchange,提问作者jvwm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:39:20