在C中使用strncat时出现的分段错误

在C中使用strncat时出现的分段错误,c,segmentation-fault,C,Segmentation Fault,所以我两周前才开始学习,基本上是个初学者。所以我写了这个程序。但它在strncat函数中连续给出分段错误行41。我不确定我做错了什么 #include <stdio.h> #include <string.h> #define _XOPEN_SOURCE #include <unistd.h> #define _GNU_SOURCE #include <crypt.h> #define WORD "/usr/share/dict/words"

所以我两周前才开始学习,基本上是个初学者。所以我写了这个程序。但它在strncat函数中连续给出分段错误行41。我不确定我做错了什么

#include <stdio.h>
#include <string.h>
#define _XOPEN_SOURCE
#include <unistd.h>

#define _GNU_SOURCE
#include <crypt.h>

#define WORD "/usr/share/dict/words"

int error(void);
int check(char *text, char *psswrd, char *salt);

int main(int argc, char *argv[])
{
    if (argc != 2)
        return error();

    char salt[3]; 
    salt[0] = argv[1][0];
    salt[1] = argv[1][1];
    salt[2] = '\0';

    FILE *fptr;
    char ch;
    char *word;
    int flag = 0;
    fptr = fopen(WORD, "r");
    if (fptr == NULL)
    {
        flag = 1;
    }
    else
    {
        do
        {
            ch = fgetc(fptr);
            if ( ch != ' ' && ch != '\n')
            {
                word = strncat(word, &ch, 1);
                if (strlen(word) == 8)
                {
                    flag = check(word, argv[1], salt);
                    if (flag == 0)
                    {
                        printf ("%s \n", word);
                        return 0;
                    }
                }
            }
            else
            {
                word = "";
            }
        }
        while (ch != EOF);

        fclose(fptr);
    }

    if (flag == 2)
    {
        printf("Password not found\n");
        return 2;
    }
}

int error(void)
{
    printf ("Usage: ./crack <encrypted keyword>\n");
    return 1;
}

int check(char *text, char *psswrd, char *salt)
{
    if (strcmp(crypt(text, salt), psswrd) == 0 )
        return 0;
    else 
        return 2;
 }
#包括
#包括
#定义_XOPEN_源
#包括
#定义GNU源
#包括
#定义单词“/usr/share/dict/words”
整数错误(无效);
int检查(字符*文本,字符*psswrd,字符*盐);
int main(int argc,char*argv[])
{
如果(argc!=2)
返回错误();
焦盐[3];
salt[0]=argv[1][0];
salt[1]=argv[1][1];
盐[2]='\0';
文件*fptr;
char ch;
字符*字;
int标志=0;
fptr=fopen(字“r”);
如果(fptr==NULL)
{
flag=1;
}
其他的
{
做
{
ch=fgetc(fptr);
如果(ch!=''&&ch!='\n')
{
word=strncat(word和ch,1);
if(strlen(word)==8)
{
标志=检查(字,argv[1],盐);
如果(标志==0)
{
printf(“%s\n”,word);
返回0;
}
}
}
其他的
{
单词=”;
}
}
while(ch!=EOF);
fclose(fptr);
}
如果(标志==2)
{
printf(“未找到密码”);
返回2;
}
}
整数错误(无效)
{
printf(“用法:./crack\n”);
返回1;
}
整数检查(字符*文本,字符*psswrd,字符*盐)
{
if(strcmp(crypt(text,salt),psswrd)==0)
返回0;
其他的
返回2;
}

您需要为“word”分配内存缓冲区:

或者最好将word声明为静态数组:

word[MaxInputSize];
在做

char *word;
您已将word声明为指向char的指针,但尚未设置
word
指向的位置。只要未分配的
word
可以指向任何地方,取消引用
word
ie
*word
就会导致未定义的行为,这正是您在中所做的

 word = strncat(word, &ch, 1);
为了使代码正常工作,在执行上述步骤之前,您需要将内存分配给
word

word=malloc(100*sizeof *ptr); // You set word to point to a chunk of 100 bytes
if strlen(word)<=98)  // remember 99 is the max allowed, you gonna add 1 char
  strncat(word, &ch, 1);
假设
word
指向100字节的块,现在

strncat(word, &ch, 1);
这在逻辑上是不正确的,因为假设单词已完全填充(99个字符加上终止的空字符),则不能再向其添加一个字符,所以在执行此步骤之前需要进行一些错误检查。做点像

word=malloc(100*sizeof *ptr); // You set word to point to a chunk of 100 bytes
if strlen(word)<=98)  // remember 99 is the max allowed, you gonna add 1 char
  strncat(word, &ch, 1);

您需要为
word
分配内存,可以将其作为数组或使用
malloc
。如果字符串很小(与堆栈大小相比),请使用数组,因为它不需要清理

您还需要设置
word[0]=0malloc
之后执行code>,否则您将收到垃圾邮件和可能的第二个分段错误

向字符串添加字符的标准方法是

char word[9];
char* pWord = word;
memset(word,0,sizeof(word));
...

  ch = getchar();
  *pWord++ = ch;
  len++;
  if (len >= sizeof(word)-1) ...

您需要为
word
分配内存。只需添加一行,如
word=(char*)malloc()
要使
ch==EOF
起作用,
ch
必须是
int
,而不是
char
。但如果将其设置为
int
,则无法将其用作
strncat
的参数。(在我看来,这没关系。
strncat
是一种可怕的方法,可以将一个字符附加到您知道其长度的字符串中。)@rici这是我现在知道的唯一方法。欢迎使用堆栈溢出。谢谢静态数组起作用了。(事实上,我发现数组的使用更容易理解)别忘了释放它。你总是想在完成后释放内存。@Mirakurun:好的,这是一个很好的做法,是的,但它们会在程序结束时自动释放。这不仅是一个很好的做法,也是为了不耗尽内存(如果在程序结束前不需要分配内存)@sjsam不认为内存是理所当然的。