【问题标题】:passing structs to functions as void pointers将结构作为 void 指针传递给函数
【发布时间】:2012-11-08 00:28:05
【问题描述】:

我正在尝试将结构的指针传递给函数,但是当我尝试访问结构时,结构内的最后一个变量在其内存地址中丢失了 1 个字节,导致使用该变量的任何内容出现段错误。

typedef struct
{
  pthread_t tID;
  int tType;
}sThread;

sThread threads[MAX_THREADS];

typedef struct
{
  int tID;
  int sock;
  int arg_count;
  char *from_p, **arg_p;
}command_struct;

pthread_t Thread_Start(void *function, void *param)
{
  pthread_t tHandle;

  pthread_create(&tHandle, NULL, function, (void*)param);

  return tHandle;
}

void cmd_test(int sock, char *from_p, char **arg_p, int arg_count)
{ 
  if(thread_check(1))
  {
    send_line(sock, "%s :test thread already running", from_p);
    return;
  }

  command_struct test;

  test.tID = thread_add(1);
  test.arg_count = arg_count;
  test.arg_p = arg_p;

  threads[test.tID].tID = Thread_Start(test_cmd, &test);
}

void *test_cmd(void *param)
{ 
  command_struct test = *((command_struct *)param);

  int i = 0;

  for(i = 1; i < test.arg_count; i++)
  {
    printf("%s", test.arg_p[i]);
  }

  thread_clear(test.tID);
  return NULL;
}

发生的事情是在 cmd_test(产生线程的函数)内部,结构被正确初始化并且所有变量都是正确的。

$1 = {tID = 0, sock = 5, arg_count = 5, from_p = 0xbffff254 "test", arg_p = 0xbfffec48}

但是从运行线程中的 test_cmd 开始,structre 缺少 arg_p 地址的 1 个字节,导致:

$1 = {tID = 0, sock = 5, arg_count = 5, from_p = 0xbffff254 "test", arg_p = 0xffec48}

如果我在我的 command_struct arg_p 的地址末尾添加一个无用的变量,那么它会变得正确,并且 command_struct 中的最后一个变量在它的内存地址中缺少 1 个字节。

【问题讨论】:

  • 有时您使用名称argp,有时使用arg。这只是试图总结问题的错误,还是实际上在调试器中称为argp,在代码中称为arg?我担心你调试的东西与你想象的不同,或者你包含了错误的头文件。解决此问题的一种方法(也有助于在 StackOverflow 上发布问题)是尝试将您的程序缩减为演示问题的最小示例。这样做可能会帮助您找到它;如果没有,你可以在这里发布完整的程序,这样更容易找到问题。
  • 这只是一个总结。对于那个很抱歉。让我尝试将示例缩减为半真实代码
  • 您使用 void 指针而不是 command_struct 指针的任何原因?
  • 在实际代码中,它实际上在线程中生成“test_cmd”,并在另一个结构中跟踪线程 ID 等。为了简单起见,我把它拿出来了。我通过以下方式调用函数: pthread_create(&tHandle, NULL, function, (void*)param); function 是函数的内存地址,param 是结构体的内存地址。我会发布真正的代码,但我怀疑你们是否愿意通读我的整个线程平台来跟踪线程,当我可以简单地简化问题时。
  • 这里没有段错误(gcc 4.6.2)。你用的是什么编译器?

标签: c memory struct


【解决方案1】:

您正在将一个指向局部变量的指针传递给您的线程 - 当线程访问它时,内存已被重新用于其他用途。

试试这个:

void cmd_test(int sock, char *from_p, char **arg_p, int arg_count)
{ 
    if(thread_check(1))
    {
        send_line(sock, "%s :test thread already running", from_p);
        return;
    }

    // === begin modified code in cmd_test():
    command_struct* test = malloc(sizeof(command_struct));

    test->tID = thread_add(1);
    test->arg_count = arg_count;
    test->arg_p = arg_p;

    threads[test.tID].tID = Thread_Start(test_cmd, test);
    // === end modified code
}

void *test_cmd(void *param)
{ 
    command_struct test = *((command_struct *)param);
    free(param);    // <-- new line of code

    // remainder is the same...
    // ...
}

【讨论】:

  • 感谢这解决了一个问题,但又带来了另一个问题。我可以通过结构传递整数,但是当我尝试传递指针或指向指针的指针时,结果在线程中始终为空白。 (在启动线程之前的 gdb 中,它看起来像 $1 = {tID = 0, str = 0xbffff096 "1.2", throt = 90, p = 10, ti = 10} 但我使用修改后的代码在线程内启动它看起来像 $2 = {tID = 0, str = 0xbffff096 "", throt = 90, p = 10, ti = 10} 的线程。(它修复了原始内存问题。)
  • 没关系,我设法通过将 str 定义为 char str[18]; 而不是 char *str 然后使用 sprintf 将我的 arg_p 变量放入其中来解决它。只是一个问题这样做是因为我没有为char *str; 分配空间吗?
猜你喜欢
  • 1970-01-01
  • 2013-01-27
  • 2020-05-15
  • 2013-06-25
  • 1970-01-01
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
相关资源
最近更新 更多