C pthread程序的一些奇怪结果

C pthread程序的一些奇怪结果,c,pthreads,C,Pthreads,这是一个非常简单的多线程程序。它将创建两个线程并运行 在线程中,它将把argv0复制到origname 第一次,原始名称是正确的 但是进入while循环后,原始名称将被sprintf损坏 它的打印方式如下: 你好,世界!是我,线程0/多线程3 origname 0./multi-thread 3 origname的内容是sprintf的参数。我不明白原因是什么。有人能帮忙吗 #include <pthread.h> #include <stdio.h> #define N

这是一个非常简单的多线程程序。它将创建两个线程并运行

在线程中,它将把
argv0
复制到
origname

第一次,原始名称是正确的

但是进入while循环后,原始名称将被
sprintf
损坏

它的打印方式如下:

你好,世界!是我,线程0/多线程3

origname 0./multi-thread 3

origname
的内容是
sprintf
的参数。我不明白原因是什么。有人能帮忙吗

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS     2
void sendstring(char *string)
{
    printf("%s",string);
}
struct thread_data{
    int  thread_id;
    char *argv0;
};

struct thread_data thread_data_array[NUM_THREADS];


void *PrintHello(void *parameter)
{
    struct thread_data *childpara;
    childpara = (struct thread_data *)parameter;
    int i = 0;
    char origname[20];
    strncpy(origname, childpara->argv0,strlen(childpara->argv0));
    origname[strlen(childpara->argv0)] = '\0';
    printf("init origname %s argv0 %s\n",origname, childpara->argv0);

    while(1)
    {
            printf("origname %s\n",origname);
            sleep(1);
            char buffer[30];
            sprintf(buffer,"Hello World! It's me, thread #%ld %s %d!\n", childpara->thread_id, childpara->argv0, i++);
            sendstring(buffer);
    }
    pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;
    for(t=0; t<NUM_THREADS; t++){
            thread_data_array[t].thread_id = t;
            thread_data_array[t].argv0 = argv[0];
            rc = pthread_create(&threads[t], NULL, PrintHello,(void *) &thread_data_array[t]);      

            if (rc){
                    printf("ERROR; return code from pthread_create() is %d\n", rc);
                    exit(-1);
            }
    }
    pthread_exit(NULL);
}
#包括
#包括
#定义NUM_线程2
void sendstring(字符*字符串)
{
printf(“%s”,字符串);
}
结构线程数据{
int-thread_-id;
char*argv0;
};
struct thread_data thread_data_数组[NUM_THREADS];
void*PrintHello(void*参数)
{
struct thread_data*childpara;
childpara=(struct thread_data*)参数;
int i=0;
charorigname[20];
strncpy(origname,childpara->argv0,strlen(childpara->argv0));
原始名称[strlen(childpara->argv0)]='\0';
printf(“初始原始名称%s argv0%s\n”,原始名称,childpara->argv0);
而(1)
{
printf(“原始名称%s\n”,原始名称);
睡眠(1);
字符缓冲区[30];
sprintf(buffer,“你好,世界!是我,线程#%ld%s%d!\n”,childpara->thread\u id,childpara->argv0,i++);
发送字符串(缓冲区);
}
pthread_exit(NULL);
}
int main(int argc,char*argv[])
{
pthread_t threads[NUM_threads];
int rc;
长t;

对于(t=0;t,您的问题来自这一行:

thread_data_array[t].argv0 = argv[0];
argv定义为
char**argv
(与
char*argv[]
相同),因此argv[0]是指针。因此,
thread\u data\u array[t]。argv0
argv
中数据的别名

最后,两个线程共享同一个字符串,所有的事情都变得一团糟。不要问我什么时候出错的确切细节,因为这样做时可能会发生很多事情,这取决于什么时候运行哪一行代码


您需要改为使用。这样,每个线程都有自己的副本,两个线程不会相互干扰。

您的问题是缓冲区溢出。我计算:

你好,世界!是我,线程#0./multi-thread 3!

超过40个字符,但您正在将其快速放入一个30字节的缓冲区中。发生这种情况后,所有赌注都被取消。结果未定义。它可能会崩溃,它可能会做一些奇怪的事情,它可能会制作一个纳米机器人,然后发送给整个开发团队购买咖啡。

这就是我想要的。我想使用argv[0]作为新创建的线程的参数。我认为这不是问题所在。我将内容从此指针复制到原始名称,但不是指针。当我对sprintf进行注释时,它工作正常。您需要理解——您没有复制内容。您只是复制指针,这意味着两个线程指向相同的内存空间。使用strcpy()。此外,输出上没有信号量/屏障/互斥体,因此当运行时,两个线程的输出偶尔会被置乱。我发现了问题。这是因为缓冲区[30]太小。内容已超出其大小,将写入同一堆栈上的origname数组中。顺便说一句,谢谢您。@Zhongshu,很高兴您找到了答案。祝您好运。