C 分段故障(堆芯转储)?
我正试图使用tokenizer.h文件头访问tokenizer.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"
分段错误(核心转储)
错误,我无法调用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*
notchar
关于: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
$