无法确定简单多线程程序中的错误

时间:2016-07-14 17:22:21

标签: c multithreading segmentation-fault

我正在开发一个涉及多线程的项目。虽然我对多线程有一个很好的理解,但我没有写过很多这样的代码。以下代码只是我为实践编写的一个简单代码。使用gcc -pthread编译时,它工作正常。

为了构建这个代码,我需要包含一些已经包含和链接pthread的库。如果我通过包含和链接这些库进行编译,那么5次中有3次会给出分段错误。 main()中的第一个 for -loop存在一些问题 - 用多个语句替换此 for -loop可以正常工作。

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

#define NUM_THREADS 3

pthread_mutex_t m_lock = PTHREAD_MUTEX_INITIALIZER;

typedef struct{
    int id;
    char ip[20];
} thread_data;

void *doOperation(void* ctx)
{
    pthread_mutex_lock(&m_lock);
    thread_data *m_ctx = (thread_data *)ctx;
    printf("Reached here\n");
    pthread_mutex_unlock(&m_lock);
    pthread_exit(NULL);
}

int main()
{
    thread_data ctx[NUM_THREADS];
    pthread_t threads[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; ++i)
    {
        char ip_n[] = "127.0.0.";
        char ip_h[4];
        sprintf(ip_h, "%d", i+1);
        strcpy(ctx[i].ip, strcat(ip_n, ip_h));
    }

    for (int i = 0; i < NUM_THREADS; ++i)
    {
        pthread_create(&threads[i], NULL, doOperation, (void *)&ctx[i]) 
    }

    for (int i = 0; i < NUM_THREADS; ++i)
    {
        pthread_join(threads[i], NULL);
    }

    pthread_exit(NULL);

}

4 个答案:

答案 0 :(得分:3)

你说你提出的代码&#34;工作得很好&#34;,但它是错误的。特别是,第一个setSize()循环是错误的,所以在某些情况下它给你带来麻烦也就不足为奇了。这是一个细分:

for

您已将 char ip_n[] = "127.0.0."; 声明为ip_n的数组,其长度足以容纳给定的初始值设定项,包括其终止空字符。

char

假设 char ip_h[4]; sprintf(ip_h, "%d", i+1); 成功,您已将非空字符串写入sprintf()数组char

ip_h

您尝试通过 strcpy(ctx[i].ip, strcat(ip_n, ip_h)); strcat()的内容附加到ip_h的末尾,但没有空间 - 这会写入超出ip_n的范围,产生不确定的行为。

解决此问题的最简单方法可能是使用足以满足完整数据的显式长度来声明ip_n。通常,点分四IP地址字符串可能需要多达16个字节,包括终结符:

ip_n

答案 1 :(得分:1)

我刚刚在;

的末尾添加了pthread_create(&threads[i], NULL, doOperation, (void *)&ctx[i])

此分段错误可能是因为

char ip_n[] = "127.0.0.";

以上,sizeof(ip_n)仅返回9。但是你需要至少10个字符来存储像127.0.0.3这样的字符串(最后包括空字符)。未经授权的内存访问可能会导致分段错误。尝试将其替换为char ip_n[10] = "127.0.0.";

答案 2 :(得分:1)

你不能strcat(ip_n, ip_h),因为数组ip_n只能容纳字符串"127.0.0."。这是手册页所说的内容,重点是

  

strcat()和strncat()函数附加了一个副本   以null结尾的字符串s2到以null结尾的字符串的结尾   s1,然后添加一个终止'\ 0'。 字符串s1必须足够   保留结果的空间。

声明应为

char ip_n[20] = "127.0.0.";

答案 3 :(得分:0)

ip_n []指向常数;编译器保留9个字节,包括NULL字节。不应该访问这9个字节之后的任何内容,如果这样做,结果是未定义的(它可能在某些时候工作,但可能不是所有时间)。当你这样做时:

digitalWrite(motoPin,HIGH);
digitalWrite(motoPin ,LOW);

你正在溢出ip_n指向的缓冲区。也许这就是造成问题的原因。如果不是,我仍然建议修复它。