5

構造体のポインターを関数に渡そうとしていますが、構造体にアクセスしようとすると、構造体内の最後の変数のメモリ アドレスから 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 バイト失われます。

4

1 に答える 1

3

ローカル変数へのポインタをスレッドに渡しています。スレッドがそれにアクセスするまでに、メモリは他の目的で再利用されています。

これを試して:

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...
    // ...
}
于 2012-11-20T02:34:03.157 に答える