Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 分段故障(堆芯转储)?_C_Memory_Segmentation Fault_Coredump - Fatal编程技术网

C 分段故障(堆芯转储)?

C 分段故障(堆芯转储)?,c,memory,segmentation-fault,coredump,C,Memory,Segmentation Fault,Coredump,我正试图使用tokenizer.h文件头访问tokenizer.c中的方法,但是当我向控制台输入内容时,如果没有收到分段错误(核心转储)错误,我无法调用main方法中的“tokenize”方法。 我尝试过重新安排指针和内存分配,我也得到了同学们的帮助。我仍然收到错误 #include <stdio.h> #include <stdlib.h> #include "tokenizer.h" #include "history.h"

我正试图使用tokenizer.h文件头访问tokenizer.c中的方法,但是当我向控制台输入内容时,如果没有收到
分段错误(核心转储)
错误,我无法调用main方法中的“tokenize”方法。 我尝试过重新安排指针和内存分配,我也得到了同学们的帮助。我仍然收到错误

#include <stdio.h>
#include <stdlib.h>
#include "tokenizer.h"
#include "history.h"

int main(){
  int noexit = 1;
  while(noexit){
    char input[100];
    printf("> ");

    fgets(input, 100, stdin);

    if(*input == '0'){
      noexit = 0;
    }
    else{
      char** tokens = tokenize(input);
      print_tokens(tokens);
      free_tokens(tokens);
    }
  }
  //past output
  /*printf(space_char(' '));*/
}
街区

#include <stdio.h>
#include <stdlib.h>
#include "tokenizer.h"

int space_char(char c){
  if(c == '\t' || c == ' '){
    return 1;
  }
  return 0;
}

int non_space_char(char c){
  if(c != '\t' || c != ' '){
    return 1;
  }
  return 0;
}

char *word_start(char *str){
  int i = 0;
  while(space_char(str[i]) == 1){
    i++;
  }
  return &str[i];
}

char *word_terminator(char *word){
  word  = word_start(word);
  int i = 0;
  
  while(non_space_char(word[i]) == 1){
    i = i+1;
  }
  
  return &word[i];
}

int count_words(char *str){
  int count = 0;
  int i = 0;
  while(str[i] != '\0') {
      if(space_char(str[i]) && non_space_char(str[i + 1]))
    count++;
      i++;
    }
    count++;
  return count;
}

char  *copy_str(char *inStr, short len){
  int i = 0;
  //MALLOC FOR NEW STR :D
  char *outStr = malloc((len+1) *sizeof(char));

  while(i<=len){
    outStr[i]  = inStr[i];
    i= i+1;
  }
  return outStr;
}

char **tokenize(char *str){
  int i = 0;
  printf("%s","int i");
  int len;
  printf("%s","len");
  int all = count_words(str);
  printf("%s","all");
  char **tokens = malloc((all+1) * sizeof(char*));
  printf("%s","tokens");
  char *pointer = str;
  printf("%s","pointer");

  while(i < all+1){
    pointer = word_start(pointer);
    printf("%s","word_start");
    len = (word_terminator(pointer) - word_start(pointer));
    printf("%s","len");
    tokens[i] = copy_str(pointer, len);
    pointer = word_terminator(pointer);
    i = i + 1;
  }
  tokens[i] = 0;
  return tokens;
}

void print_tokens(char **tokens){
  int i = 0;
  while(tokens[i] !=  NULL){
    printf("%s\n", tokens[i]);
    i =  i + 1;
  }
}

void free_tokens(char **tokens){
  int i = 0;
  //can't pass  len as param  :D
  while(tokens[i] != 0){
    free(tokens[i]);
    i = i + 1;
  }
  free(tokens);
}
#包括
#包括
#包括“tokenizer.h”
整数空间字符(字符c){
如果(c='\t'| | c=''){
返回1;
}
返回0;
}
int非字符空间字符(字符c){
如果(c!='\t'| | c!=''){
返回1;
}
返回0;
}
char*word\u开始(char*str){
int i=0;
while(space_char(str[i])==1){
i++;
}
返回&str[i];
}
字符*字_终止符(字符*字){
word=word\u开始(word);
int i=0;
while(非空间字符(字[i])==1){
i=i+1;
}
返回&word[i];
}
整数计数_字(字符*str){
整数计数=0;
int i=0;
while(str[i]!='\0'){
if(空格字符(str[i])&非空格字符(str[i+1]))
计数++;
i++;
}
计数++;
返回计数;
}
字符*复制\u str(字符*仪表,短透镜){
int i=0;
//新STR的MALLOC:D
char*outsr=malloc((len+1)*sizeof(char));

虽然(我嗯,我试着编译你的代码

首先,在
tokenizer.h
文件中,
start\u word()
函数声明为返回字符,但在
tokenizer.c
文件中,定义为返回
char*
。根据
tokenizer.h
中的描述,将其更改为返回
char*

/* Returns a pointer to the first character of the next 
   space-separated word in zero-terminated str.  Return a zero pointer if 
   str does not contain any words. */
char *word_start(char *str);
现在,查看
tokenizer.c
文件中的
tonkenize()
函数,发现
printf()
函数没有正确使用。要了解如何使用
printf()
,请选中

  • 根据正在打印的变量类型更改说明符。
    “%s”
    仅适用于字符串
  • 然后,添加
    '\n'
    (新行字符)。只有在到达
    '\n'
    后,才会打印缓冲区中的字节
  • 最后,删除变量名中的引号。在C中,引号始终表示字符串
  • 以下是一些例子:

    int i = 0;
    printf("%d\n", i);
    int len;
    printf("%d\n", len);
    int all = count_words(str);
    printf("%d\n", all);
    // (...)
    
    如果您不打算打印变量,并且这些
    printf()
    调用仅用于测试,请删除第一个参数(但不要忘记
    '\n'
    字符)

    在这些
    printf()
    调用之后,使用
    malloc()
    分配内存

    如果
    tokens
    变量表示以null结尾的字符串数组,并且变量
    all
    表示变量
    tokens
    具有的字符串数,则该值是正确的。问题是您没有检查内存分配是否成功

    char **tokens = malloc((all+1) * sizeof(char*));
    if (tokens == NULL) {
        fprintf(stderr, "error: allocating memory\n");
        return NULL;
    }
    
    现在,关于while循环

  • 首先获取单词的开头,然后计算长度,再次调用
    word\u start()
    ,但您已经知道单词的开头
  • 然后,复制字符串并移动到单词的末尾,再次调用
    word\u terminator()
    函数,而不仅仅是存储以前的结果
  • i=i+1;
    指令可以替换为
    i++;
  • 迭代的范围必须是从零到字符串数减去一
  • 下面是我对
    tokenize()
    函数的建议

    char **tokenize(char *str) {
        int i = 0;
        int all = count_words(str);
        char **tokens = malloc((all+1) * sizeof(char*));
        if (tokens == NULL) {
            fprintf(stderr, "error: allocating memory\n");
            return NULL;
        }
        char *start = str, *end = str;
        while (i < all) {
            start = word_start(end);
            end = word_terminator(start);
            tokens[i] = copy_str(start, end - start);
            i++;
        }
        tokens[i] = NULL;
        return tokens;
    }
    
    char *copy_str(char *inStr, short len) {
        int i = 0;
        char *outStr = malloc((len+1) *sizeof(char));
        if (outStr == NULL) {
            fprintf(stderr, "error: allocating memory\n");
            return NULL;
        }
        while (i < len) {
            outStr[i] = inStr[i];
            i++;
        }
        outStr[i] = '\0';
        return outStr;
    }
    
    查看
    word\u start()
    word\u terminator()
    的实现方式,我们可以清楚地理解,如果我调用
    word\u start(“”;
    word\u terminator(“asdfg”);
    ,将出现分段错误。这是因为您仅在分别到达非空格/空格字符时进行检查。您需要检查
    '\0'
    (空字符)以在字符串末尾中断循环

    char *word_start(char *str) {
        int i = 0;
        while (space_char(str[i]) == 1) {
            if ( str[i] == '\0' )
                return NULL;
            i++;
        }
        return &str[i];
    }
    
    char *word_terminator(char *word) {
        word  = word_start(word);
        if ( word == NULL )
            return NULL;
        int i = 0;
        while (non_space_char(word[i]) == 1) {
            if ( word[i] == '\0' )
                return &word[i-1];
            i++;
        }
        return &word[i];
    }
    
    再次编译程序后,结果如下

    $ ./uimain
    > Miguel Carvalho 22
    Miguel Carvalho 22
    
    
    > ^C
    $
    
    虽然程序运行正常,但代码还是可以改进的

  • C标准库包含一些用于此程序的有用函数。搜索
    ctype.h
    string.h
  • count\u words()
    函数计数不正确。请尝试在循环中使用
    space\u char()
    non\u space\u char()
    函数,而不是使用
    word\u start()
    word\u terminator()
    函数,直到返回
    NULL
    为止

  • 使用调试器。它会立即告诉您触发seg故障的确切代码行。这是您应该做的最小调试,并且应该在问题中发布。
    -fsanize=address
    (gcc&我认为clang)非常适合调试这些问题。首先,
    char word\u start(char*str);
    当然不符合它的注释描述。该函数应该返回一个
    char*
    not
    char
    关于:
    char*outtr=malloc((len+1)*sizeof(char));
    1)表达式:
    sizeof(char)
    在C标准中定义为1。将任何值乘以1都没有效果,只会弄乱代码。建议删除该表达式。2)函数:
    malloc()
    需要一个
    size\u t
    参数,而不是
    short
    参数。3)函数:
    malloc()
    可能会失败,因此应始终选中(!=NULL)用于确保操作成功的返回值。如果不成功(=NULL),则调用
    perror(“malloc failed”);
    清除并退出与以下语句相关的程序:
    printf(“%s”,“word\u start”)
    这将位于
    stdout
    流缓冲区中,直到:
    程序退出
    ,或
    缓冲区溢出
    执行输入操作
    。或调用
    fflush()
    或输出“\n”。也就是说,这不会以“及时”的方式显示在终端上。建议:
    printf(“%s\n”,“开始”一词;
    
    char **tokenize(char *str) {
        int i = 0;
        int all = count_words(str);
        char **tokens = malloc((all+1) * sizeof(char*));
        if (tokens == NULL) {
            fprintf(stderr, "error: allocating memory\n");
            return NULL;
        }
        char *start = str, *end = str;
        while (i < all) {
            start = word_start(end);
            end = word_terminator(start);
            tokens[i] = copy_str(start, end - start);
            i++;
        }
        tokens[i] = NULL;
        return tokens;
    }
    
    char *copy_str(char *inStr, short len) {
        int i = 0;
        char *outStr = malloc((len+1) *sizeof(char));
        if (outStr == NULL) {
            fprintf(stderr, "error: allocating memory\n");
            return NULL;
        }
        while (i < len) {
            outStr[i] = inStr[i];
            i++;
        }
        outStr[i] = '\0';
        return outStr;
    }
    
    char *word_start(char *str) {
        int i = 0;
        while (space_char(str[i]) == 1) {
            if ( str[i] == '\0' )
                return NULL;
            i++;
        }
        return &str[i];
    }
    
    char *word_terminator(char *word) {
        word  = word_start(word);
        if ( word == NULL )
            return NULL;
        int i = 0;
        while (non_space_char(word[i]) == 1) {
            if ( word[i] == '\0' )
                return &word[i-1];
            i++;
        }
        return &word[i];
    }
    
    $ ./uimain
    > Miguel Carvalho 22
    Miguel Carvalho 22
    
    
    > ^C
    $