【问题标题】:Save a file to a string within a specific thread将文件保存到特定线程中的字符串
【发布时间】:2018-02-04 03:20:12
【问题描述】:

我正在尝试将文本文件保存到线程内的 C 中的字符串中,但我不断收到分段错误。这发生在正在创建的线程的实例中。我以前没有使用过线程,所以我不确定这是否会导致问题。

int getCurrentSegmentWordcount(int segment) { //declaring file pointer (value?)
    printf("func\n");
    char text[1000];
    char buffer[150];
    FILE *fp = fopen("words.txt", "r");
    if(fp == NULL) {
        printf("null file");
    }
    int i = 0;
    // while(feof(fp)) {
    //  text[i++] = fgetc(fp);
    // }
    // text[i] = '\0'; //set null char to end string

    while(fgets(buffer, 150, fp)) {
        strcpy(text[i], buffer);
        printf("\n\n %s \n\n", text[i]);
        i++;
    }
    getchar();

    pthread_exit(NULL);
}

以下是我的编译器警告。没有错误,但有多个警告。

assign2.c: In function ‘print_hello_world’:
assign2.c:10:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘void *’ [-Wformat=]
  printf("Hello World. Greetings from thread %d\n", tid);
         ^
assign2.c: In function ‘getCurrentSegmentWordcount’:
assign2.c:29:10: warning: passing argument 1 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
   strcpy(text[i], buffer);
          ^
In file included from assign2.c:4:0:
/usr/include/string.h:125:14: note: expected ‘char * restrict’ but argument is of type ‘char’
 extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
              ^
assign2.c:30:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
   printf("\n\n %s \n\n", text[i]);
          ^
assign2.c: In function ‘main’:
assign2.c:46:77: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
   status = pthread_create(&threads[i], NULL, getCurrentSegmentWordcount(i), (void * )i);
                                                                             ^
assign2.c:46:46: warning: passing argument 3 of ‘pthread_create’ makes pointer from integer without a cast [-Wint-conversion]
   status = pthread_create(&threads[i], NULL, getCurrentSegmentWordcount(i), (void * )i);
                                              ^
In file included from assign2.c:1:0:
/usr/include/pthread.h:233:12: note: expected ‘void * (*)(void *)’ but argument is of type ‘int’
 extern int pthread_create (pthread_t *__restrict __newthread,
            ^
assign2.c:52:7: warning: passing argument 1 of ‘exit’ makes integer from pointer without a cast [-Wint-conversion]
  exit(NULL);
       ^
In file included from assign2.c:3:0:
/usr/include/stdlib.h:543:13: note: expected ‘int’ but argument is of type 

‘void *’
     extern void exit (int __status) __THROW __attribute__ ((__noreturn__));
./assign2exec
Main here. Creating thread 0
func
Makefile:20: recipe for target 'all' failed
make: *** [all] Segmentation fault (core dumped)

【问题讨论】:

  • 在这个语句中“strcpy(text[i], buffer);”什么是“文本[i]”...??它需要是什么???另外,“i++”是正确的做法吗..??
  • 你的编译器警告告诉你什么?
  • text[i] 是字符串文本中的当前字符。我相信 i++ 是正确的,因为我们必须移动到下一个字符。我的编译器说分段错误
  • 检查“strcpy()”上的“man”页面...它的第一个参数的类型是什么?您确实收到了关于它的编译器警告...警告行以“assign2.c:29:10:”开头(顺便说一句,这些提示可以帮助您在没有人告诉您的情况下找到答案。)

标签: c gcc segmentation-fault


【解决方案1】:

你要做的第一件事是阅读编译器警告,而不是忽略 他们。他们在那里给你提示你做错了什么,他们不是 在那里惹你生气。

函数strcpy有这个签名:

#include <string.h>

char *strcpy(char *dest, const char *src);

从这里很明显,它期望dest 是指向char 数组的指针 src 指向的字符串将被保存在哪里。

你声明了char buffer[150];,所以buffer是一个char数组,buffer[i] 将返回一个 char。所以你将错误的类型传递给strcpy

编译器告诉你这个:

assign2.c: In function ‘getCurrentSegmentWordcount’:
assign2.c:29:10: warning: **passing argument 1 of ‘strcpy’ makes pointer from integer without a cast** [-Wint-conversion]
   strcpy(text[i], buffer);

您需要有一个二维char 数组或char 指针数组 为了保存这个。第一个是最容易写的:

char text[1000][1000];

唯一的问题是它在行数上有一个固定的长度,如果文件有 超过 1000 行,您不能将它们全部存储在缓冲区中。

第二个选项更健壮:

int getCurrentSegmentWordcount(int segment) {
    char (*text)[1000] = NULL, char (*tmp)[1000];

    ...
    i = 0;
    while(fgets(buffer, sizeof buffer, fp)) {

        // removing possible \n from buffer, you probably
        // want that
        buffer[strcspn(buffer, "\n")] = 0;

        tmp = realloc(text, (i+1) * sizeof *tmp);
        if(tmp == NULL)
        {
            // error, cannot continue
            free(text);
            return;
        }

        text = tmp;
        strcpy(text[i], buffer);
        printf("\n\n %s \n\n", text[i]);
        i++;
    }
    ...

    free(text); // freeing the memory
}

而且这个版本更多,它可以处理不同长度的线条

int getCurrentSegmentWordcount(int segment) {
    char **text = NULL, **tmp;

    ...
    i = 0;
    while(fgets(buffer, sizeof buffer, fp)) {

        // removing possible \n from buffer, you probably
        // want that
        buffer[strcspn(buffer, "\n")] = 0;

        tmp = realloc(text, (i+1) * sizeof *tmp);
        if(tmp == NULL)
        {
            // error, cannot continue
            free(text);
            return;
        }

        text = tmp;

        text[i] = calloc(strlen(buffer) + 1, 1);

        if(text[i] == NULL)
        {
            // error, free all the allocated memory:
            for(int j = 0; j < i; ++j)
                free(text[j]);

            free(text);

            return;

        }

        strcpy(text[i], buffer);
        printf("\n\n %s \n\n", text[i]);
        i++;
    }
    ...

    // freeing the memory
    for(int j = 0; j < i; ++i)
        free(text[i]);

    free(text);
}

我不知道这是否只是您的示例,但您的功能有点毫无意义。 您将这些行存储在缓冲区中,但根本不对其进行任何操作。这 如果您返回 text 或使用 它。

编译器警告和错误会显示您必须执行的所有行 改进你的代码。一条有趣的线是:

assign2.c:52:7: warning: passing argument 1 of ‘exit’ makes integer from pointer without a cast [-Wint-conversion]
  exit(NULL);

正确的调用是

exit(0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-03
    • 2014-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    相关资源
    最近更新 更多