c - pthread create 中传递的结构参数被破坏

标签 c multithreading gnu

我有一个名为 command 的结构,如下所示。枚举中的第一个值是 AND_COMMAND

struct command
{
  enum command_type type;
  int status;
  char *input;
  char *output;
  union
  {
    struct command *command[2];
    char **word;
    struct command *subshell_command;
  } u;
};

当我调用 pthread_create 时,我以 command_t 的形式向它传递一个命令(强制转换为 (void *))。

typedef struct command *command_t;

我的线程采用这个 (void *) command_t,将其转换回 (command_t) 并尝试使用该结构。

void execute_thread(void *c) {
  command_t command = (command_t) c;

但是,当我将结构传递给execute_thread时,第一个值被清零。如果我的 command_type 为 SIMPLE_COMMAND 且状态为 -1,则当它传递到线程时,command_type 为 AND_COMMAND,状态为 0。但是,结构中的其他值都没有更改。更奇怪的是这种数据篡改何时发生。我能够在 gdb 中捕获该现象:

445   command_t command = (command_t) c;
(gdb) p *((command_t) c)
$6 = {type = SIMPLE_COMMAND, status = -1, input = 0x605370 "abc", output = 0x605390 "def", u = {
command = {0x6052e0, 0x0}, word = 0x6052e0, subshell_command = 0x6052e0}}
(gdb) n
(gdb) p *((command_t) c)
$7 = {type = AND_COMMAND, status = 0, input = 0x605370 "abc", output = 0x605390 "def", u = {command = {
  0x6052e0, 0x0}, word = 0x6052e0, subshell_command = 0x6052e0}}

看起来 c 指向的结构在使用 (command_t) c; 进行转换之前不会改变; 我对这种行为完全感到困惑。我不认为转换指针可以改变它指向的值。有人可以指点一下吗,哈哈,这到底是怎么回事?我将非常感激。

最佳答案

What's more curious is when this data mangling occurs. I was able to capture the phenomenon in gdb:

这里的措辞让我相信这个问题不是确定性的;即,有时它不会发生,或者在您碰巧在问题中的 gdb 中捕获时它不会发生。

如果是这种情况(也许即使不是),我怀疑你的问题是你在主线程(或其他任何线程)中浪费了分配给 struct 命令 的内存线程正在创建 execute_thread() 线程)。您没有向我们展示线程创建代码,但是如果您使用局部变量并将其地址传递给创建的线程,那么确保局部变量的生存期不会在第二个线程之前到期可能会很棘手开始使用它。您可能想要传入已在堆上分配的struct command:

struct command* thread_data = malloc(sizeof(struct command));
struct_command_init(thread_data);

pthread_create(/* ... */, thread_data);
// ...

execute_command() 线程中:

void* execute_command(void* p)
{
    struct command cmd = *(struct command*)p;
    free(p);

    // use cmd to get at the structure data passed in...
}

请记住,struct 命令 中的各种指针引用的数据也需要对其生命周期和所有权进行明确管理。

关于c - pthread create 中传递的结构参数被破坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14670606/

相关文章:

c# - 如何在不阻塞主 UI 线程的情况下等待事件处理程序的返回值

c - VB6中如何从指针获取字符串

c++ - 什么时候不使用原子操作?

java - Java 多久同步一次内存?

C: 在 Windows 中运行 Unix 配置文件

c - POSIX 系统上 regex.h header 的不同实现背后的算法类型

c - 使用 GNU Blas 子程序在 vector 和矩阵之间进行元素乘积

c - 链表 : strange muddle of member element during output

c - c 中的 malloc() 和 free() 数组

c - 从字节的 char[] 中获取 int