【问题标题】:Segmentation fault while using strncat in C在 C 中使用 strncat 时出现分段错误
【发布时间】:2016-08-03 17:14:26
【问题描述】:

所以我两周前才开始学习,基本上是个初学者。所以我写了这个程序。但它在 strncat 函数中不断给出 Segmentation fault 错误行 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;
 }

【问题讨论】:

  • 你需要为word分配内存。
  • 加一行word = (char *) malloc(&lt;memsize&gt;);
  • 要使 ch == EOF 工作,ch 必须是 int,而不是 char。但是,如果您将其设为int,您将无法将其用作strncat 的参数。 (在我看来,这并不重要。strncat 是一种将字符附加到长度已知的字符串的可怕方法。)
  • @rici 这是我现在知道的唯一方法。

标签: c segmentation-fault


【解决方案1】:

在做

char *word;

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

 word = strncat(word, &ch, 1);

为了使代码正常工作,您需要在上述步骤之前将内存分配给word,即执行类似的操作

word=malloc(100*sizeof *ptr); // You set word to point to a chunk of 100 bytes

现在假设 word 指向一个 100 字节的块

strncat(word, &ch, 1);

逻辑上不正确,因为假设 word 已完全填满(99 个字符加上终止空字符),您不能再添加一个字符,因此您需要在此步骤之前进行一些错误检查。做类似的事情

if strlen(word)<=98)  // remember 99 is the max allowed, you gonna add 1 char
  strncat(word, &ch, 1);

作为一个好的做法,你可以在使用后删除内存,即

free(word);

【讨论】:

  • 你总是想在完成后释放内存。
  • @Mirakurun :嗯,作为一个好习惯,是的,但是当程序结束时它们会自动释放
  • 不仅是一个好习惯,也是为了不耗尽内存(如果在程序结束之前不需要分配内存)
  • @sjsam 不要把记忆当成理所当然。
【解决方案2】:

你需要为“word”分配一个内存缓冲区:

word = malloc(MaxInputSize);

或者更好的方法是将 word 声明为静态数组:

word[MaxInputSize];

【讨论】:

  • 谢谢。静态数组起作用了。 (其实我发现数组的使用更容易理解)
  • 别忘了释放它。
【解决方案3】:

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

你还需要在malloc之后设置word[0]=0;,否则你会得到垃圾和可能的第二个分段错误。

向字符串添加字符的规范方法是

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

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

【讨论】:

    猜你喜欢
    • 2015-01-20
    • 1970-01-01
    • 2021-06-13
    • 2013-04-03
    • 2016-09-15
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 2011-02-27
    相关资源
    最近更新 更多