找到你要的答案

Q:segmentation fault on c program

Q:C程序分割故障

I want to do a c program which receives some arguments.The first argument is a file and the other arguments are words.The program will create a thread for every word and will count the number of occurences in the file.I used a shell script(prts.sh) to count the occurences of the word in file.I wrote the code but when i try to run it i get segmentation fault .I'm sending through a struct the file and the argument.i think the problem is when i try to acces the elements of the struct i send in the thread funciton.This is the code i wrote so far:

#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define N 1000
int sum=0;
int n;

typedef struct {
char arg1[N];
char arg2[N];
} Mesaj;

pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
void* func(void *p){
    Mesaj *msg_func=(Mesaj*)p;
    char cmd[N];
    char result[N];
    FILE *fp;
    pthread_mutex_lock(&m);
    sprintf(cmd,"/home/alexdamian/prts.sh %s %s",msg_func->arg1,msg_func->arg2);  
    fp = popen(cmd, "r");
    fgets(result, N, fp);
    pclose(fp); 
    int n=atoi((char*)result);
    sum=sum+n;
    pthread_mutex_unlock(&m);
    free(msg_func);
    return NULL;
}
int main(int argc,char *argv[]){

pthread_t *th=malloc(argc*sizeof(pthread_t));


int i;
for(i=1;i<argc;i++){

    Mesaj *msg=malloc(sizeof(Mesaj));
    strcpy(msg->arg1,argv[i]);
    strcpy(msg->arg2,argv[i+1]);    

    pthread_create(th+i,NULL,func,msg);
}

for(i=0;i<argc;i++){
    pthread_join(*(th+i),NULL);
}
printf("the sum is %d\n",sum);
free(th);
return 0;

}

我想做一个C程序接收一些参数,第一个参数是一个文件和其他参数的话,程序将创建一个每个单词和线程将文件中出现的次数。我用一个shell脚本(PRTS。SH)数字出现在文件。我写的代码,但是当我尝试运行它我得到分割的错。我将通过结构文件和争论。我认为,问题是当我尝试访问该结构元素我发送线程功能。这是我写的代码为止:

#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#define N 1000
int sum=0;
int n;

typedef struct {
char arg1[N];
char arg2[N];
} Mesaj;

pthread_mutex_t m=PTHREAD_MUTEX_INITIALIZER;
void* func(void *p){
    Mesaj *msg_func=(Mesaj*)p;
    char cmd[N];
    char result[N];
    FILE *fp;
    pthread_mutex_lock(&m);
    sprintf(cmd,"/home/alexdamian/prts.sh %s %s",msg_func->arg1,msg_func->arg2);  
    fp = popen(cmd, "r");
    fgets(result, N, fp);
    pclose(fp); 
    int n=atoi((char*)result);
    sum=sum+n;
    pthread_mutex_unlock(&m);
    free(msg_func);
    return NULL;
}
int main(int argc,char *argv[]){

pthread_t *th=malloc(argc*sizeof(pthread_t));


int i;
for(i=1;i<argc;i++){

    Mesaj *msg=malloc(sizeof(Mesaj));
    strcpy(msg->arg1,argv[i]);
    strcpy(msg->arg2,argv[i+1]);    

    pthread_create(th+i,NULL,func,msg);
}

for(i=0;i<argc;i++){
    pthread_join(*(th+i),NULL);
}
printf("the sum is %d\n",sum);
free(th);
return 0;

}

answer1: 回答1:

Your code requires some fixes:

  1. Style and formatting, the code must be beautiful, easy on the eyes.
  2. Do not use malloc() when you don't need to.
  3. Do not use pointer arithmetic notation when you can use index notation.
  4. Always check the return values of functions

The actual problem: you iterate through all the arguments passed to the program and access 1 argument beyond the last.

This for loop:

int i;
for(i=1;i<argc;i++){

    Mesaj *msg=malloc(sizeof(Mesaj));
    strcpy(msg->arg1,argv[i]);
    strcpy(msg->arg2,argv[i+1]);    

    pthread_create(th+i,NULL,func,msg);
}

Should be:

int i;
for (i = 1 ; i < argc - 1 ; i++)
{    
    Mesaj *msg;

    msg = malloc(sizeof(*msg));
    if (msg == NULL) /* do anything except dereferencing `msg' */
        continue;
    strcpy(msg->arg1, argv[i]);
    strcpy(msg->arg2, argv[i + 1]);    

    pthread_create(&th[i], NULL, func, msg);
}

I fixed your program to show some things that you can improve:

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

#define N 1000

typedef struct
{
    char arguments[2][N];
    int *data;
} Mesaj;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *
function(void *data)
{
    Mesaj      *message;
    int        *value;
    char        cmd[N];
    char        result[N];
    FILE       *pipe;
    const char *format;

    message = (Mesaj*) data;
    value   = (int *) message->data;
    format  = "/home/iharob/prts.sh %s %s";

    snprintf(cmd, sizeof(cmd), format, 
        message->arguments[0], message->arguments[1]);
    pipe = popen(cmd, "r");
    if (pipe != NULL)
    {
        fgets(result, sizeof(result), pipe);
        pclose(pipe);

        /* This section should be protected with mutex */
        pthread_mutex_lock(&mutex);
        *value = *value + strtol(result, NULL, 10);
        pthread_mutex_unlock(&mutex);
    }
    else
        fprintf(stderr, "cannot execute the command...\n");

    free(message);

    return NULL;
}

int main(int argc,char *argv[])
{
    pthread_t  thread[argc];
    int        i;
    int        value;

    value = 0;
    for (i = 1 ; i < argc - 1 ; i++)
    {
        Mesaj *message;

        message = malloc(sizeof(*message));
        if (message != NULL)
        {
            message->data = &value;

            strcpy(message->arguments[0], argv[i]);
            strcpy(message->arguments[1], argv[i + 1]);

            pthread_create(&thread[i], NULL, function, message);
        }
    }

    for (i = 1 ; i < argc - 1 ; i++)
        pthread_join(thread[i], NULL);
    printf("The sum is %d\n", value);

    return 0;
}

For example, you don't need a single global variable in this program you can create the variable in the stack and pass it as part of the message, and you only need to malloc() the message so it exists when the thread starts, using VLAs1 you can declare an array of threads instead of malloc()ing one, which is not wrong, but you should avoid it if you can.


1Variable Length Arrays

您的代码需要一些修复:

  1. Style and formatting, the code must be beautiful, easy on the eyes.
  2. Do not use malloc() when you don't need to.
  3. Do not use pointer arithmetic notation when you can use index notation.
  4. Always check the return values of functions

实际的问题:你遍历所有的参数传递给程序和访问1个超越过去。

这个for循环:

int i;
for(i=1;i<argc;i++){

    Mesaj *msg=malloc(sizeof(Mesaj));
    strcpy(msg->arg1,argv[i]);
    strcpy(msg->arg2,argv[i+1]);    

    pthread_create(th+i,NULL,func,msg);
}

应该是:

int i;
for (i = 1 ; i < argc - 1 ; i++)
{    
    Mesaj *msg;

    msg = malloc(sizeof(*msg));
    if (msg == NULL) /* do anything except dereferencing `msg' */
        continue;
    strcpy(msg->arg1, argv[i]);
    strcpy(msg->arg2, argv[i + 1]);    

    pthread_create(&th[i], NULL, func, msg);
}

我修正了你的程序来展示一些你可以改进的东西:

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

#define N 1000

typedef struct
{
    char arguments[2][N];
    int *data;
} Mesaj;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *
function(void *data)
{
    Mesaj      *message;
    int        *value;
    char        cmd[N];
    char        result[N];
    FILE       *pipe;
    const char *format;

    message = (Mesaj*) data;
    value   = (int *) message->data;
    format  = "/home/iharob/prts.sh %s %s";

    snprintf(cmd, sizeof(cmd), format, 
        message->arguments[0], message->arguments[1]);
    pipe = popen(cmd, "r");
    if (pipe != NULL)
    {
        fgets(result, sizeof(result), pipe);
        pclose(pipe);

        /* This section should be protected with mutex */
        pthread_mutex_lock(&mutex);
        *value = *value + strtol(result, NULL, 10);
        pthread_mutex_unlock(&mutex);
    }
    else
        fprintf(stderr, "cannot execute the command...\n");

    free(message);

    return NULL;
}

int main(int argc,char *argv[])
{
    pthread_t  thread[argc];
    int        i;
    int        value;

    value = 0;
    for (i = 1 ; i < argc - 1 ; i++)
    {
        Mesaj *message;

        message = malloc(sizeof(*message));
        if (message != NULL)
        {
            message->data = &value;

            strcpy(message->arguments[0], argv[i]);
            strcpy(message->arguments[1], argv[i + 1]);

            pthread_create(&thread[i], NULL, function, message);
        }
    }

    for (i = 1 ; i < argc - 1 ; i++)
        pthread_join(thread[i], NULL);
    printf("The sum is %d\n", value);

    return 0;
}

例如,你不需要一个全局变量在本程序中可以创建堆栈中的变量和作为消息的一部分通过它,你只需要malloc()消息有当线程启动时,使用vlas1可以声明线程数组而不是malloc() ING,这是没有错,但是你如果你能避免它。


1variable长度的数组

c  segmentation-fault  core