我在第24行(fgets)中遇到了分段错误(核心转储)错误。我不是很熟悉c,但我必须为我的课程制作一个程序。我有以下代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[]){
FILE *fd1, *fd2;
char *str1, *str2;
char *salt, *hash, *key, *key1;
char buf[13], word[200], pass[200];
if(argc != 2){
fprintf(stderr, "Usage: %s <file shadow>\n", argv[0]);
exit(1);
}
str1 = (char*) malloc(100);
str2 = (char*) malloc(100);
fd1 = fopen(argv[1], "r");
fprintf(stderr, "Please, wait...\n");
while(fgets(str1, 100, fd1) != NULL){
str2 = strstr(str1, "$1$");
if(str2 != NULL){
key = strtok(str2, ":");
snprintf(pass, sizeof(pass), "%s", key);
printf("pass=%s (%lu)\n", pass, strlen(pass));
strtok(key, "$");
salt = strtok(NULL, "$");
hash = strtok(NULL, "\0");
snprintf(buf, sizeof(buf), "$1$%s$", salt);
fd2 = fopen("polish.txt", "r");
while(fgets(word, 200, fd2) != NULL){
(&word[strlen(word)])[-1] = '\0';
key1 = crypt(word, buf);
if(!strncmp(key1, pass, strlen(key1))){
printf("OK!, The password is: %s\n\n", word);
break;
}
}
}
}
fclose(fd1);
fclose(fd2);
free(str1);
free(str2);
return 0;
}
当我尝试读取/ etc / shadow文件时,它会引发我的分段错误(也尝试使用自定义txt文件)。谁能看看这个?
答案 0 :(得分:2)
从代码中的许多问题中,最重要的问题是
您不需要强制转换 malloc
,这不是必需的,可能导致无法解决的错误。
您无需使用 malloc
获取固定大小的本地变量。
您永远不会检查失败时返回NULL
的任何函数的返回值,即此函数
malloc()
fopen()
strok()
所有这些函数在失败时返回NULL
。
您malloc
并指示指针str2
,但随后您将其覆盖
str2 = strstr(str1, "$1$");
没有必要这样做,这意味着你不明白指针是如何工作的。 strstr()
返回一个指向传递给它的同一个字符串的指针,只是增加指向你要查找的子字符串的开头,或NULL
如果找不到它。
你有
key = strtok(str2, ":");
/* some other code */
strtok(key, "$");
您fclose
循环外的fd2
I / O流,while
I / O流,但您fopen()
内置fopen
它比你fclose
它的次数多很多倍。
您有两种选择,可以在fclose()
循环中移动while
,也可以将fopen()
移到while
循环之外,第二种当然是,更好。
这是错误的,因为你指向相同字符串的增量指针,你必须这样做,阅读strtok()
strtok(NULL, "$");
如您所见,您有很多潜在的未定义行为,特别是在代码中取消引用NULL
指针,如果您想阻止SEGMENTATION FAULT
,则应该修复所有这些内容。< / p>
看到程序员忽略这些东西是相当普遍的,但你应该确保你的程序不会崩溃,只需要小心。
NULL
。NULL
置于声明之后或之后,这样你可以确保如果它还没有指向任何东西,那么它是NULL
,你可以检查它。处理指针是一件非常困难的事情,但是一旦你养成这些好习惯,你就永远不会再有愚蠢的错误 - &gt; 嗯,几乎从不!
答案 1 :(得分:1)
C没有像Java这样的异常机制。唯一的方法是获取有关错误的信息,以检查函数返回的值,有时获取更多信息errno
。
在您的代码中,您应该检查fopen
是否成功,如果没有退出并显示错误信息。
您的程序崩溃了,因为您可能会尝试阅读由于fopen
返回NULL
而无法获得读取权限的文件。它的修补程序是以root身份或sudo
运行程序。
修改强>
我试过了,你的程序崩溃了:
编程接收信号SIGSEGV,分段故障。 iofgets.c上的_IO_fgets(buf = 0x7fffffffd6a0&#34;&#34;,n = 200,fp = 0x0):50 50 iofgets.c:没有这样的文件或目录。
因为我添加它时没有 polish.txt ,运行顺畅而没有错误
答案 2 :(得分:1)
问题是此行没有错误检查:
fd1 = fopen(argv[1], "r");
fopen()
returns指向已填充的FILE
对象的指针,如果无法打开文件,则为NULL
(文件不存在,或者用户没有足够的特权阅读它)。
结果,NULL
指针被传递到第24行的fgets()
调用中。
你应该检查它是否为NULL:
fd1 = fopen(argv[1], "r");
if (fd1 == NULL)
{
fprintf(stderr, "Couldn't open file for reading\n");
exit(1);
}
在我们关于NULL指针的主题的地方,你也应该检查对malloc()
的调用。这些不太可能失败,但也可能导致第24行的崩溃。
答案 3 :(得分:0)
// always check returned values from system I/O functions
// always enable all warnings so problems are addressed
// do not use 'magic' numbers
// initialize local variables that are pointers
// (and generally all local variables)
// when an error is encountered during execution,
// then release allocated memory, close files before exiting
// always look for and handle errors during execution
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <crypt.h> // <-- added for crypt() function
#define MAX_WORD_LEN (200)
#define MAX_STR_LEN (100)
#define MAX_BUF_LEN (13)
int main(int argc, char* argv[])
{
FILE *fd1 = NULL;
FILE *fd2 = NULL;
char *str1 = NULL;
char *str2 = NULL;
char *salt, *hash, *key, *key1;
char buf[MAX_BUF_LEN] = {'\0'};
char word[MAX_WORD_LEN] = {'\0'};
char pass[MAX_WORD_LEN] = {'\0'};
if(argc != 2)
{
fprintf(stderr, "Usage: %s <file shadow>\n", argv[0]);
exit(1);
}
// implied else, command line parameter count correct
if( NULL == (str1 = malloc(MAX_STR_LEN) ))
{ // then, malloc failed
perror( "malloc for str1 failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
if( NULL == (str2 = malloc(MAX_STR_LEN) ))
{ // then, malloc failed
perror( "malloc for str2 failed" );
free( str1 ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, malloc successful
if( NULL == (fd1 = fopen(argv[1], "r") ) )
{ // then fopen failed
perror( "fopen for parameter file name failed" );
free( str1 ); // cleanup
free( str2 );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
fprintf(stderr, "Please, wait...\n");
while( fgets(str1, MAX_STR_LEN, fd1) )
{
if( NULL == (str2 = strstr(str1, "$1$") ) )
{ // then, strstr failed
perror( "strstr for $1$ failed" );
continue;
}
// implied else, strstr successful
if( NULL != (key = strtok(str2, ":") ) )
{ // then, strtok failed
perror( "strtok for : failed" );
continue;
}
// implied else, strtok successful
snprintf(pass, sizeof(pass), "%s", key);
printf("pass=%s (%lu)\n", pass, strlen(pass));
if( NULL == strtok(key, "$") )
{ // then strtok failed
perror( "strtok for $ failed" );
continue;
}
// implied else, strtok successful
if( NULL == (salt = strtok(NULL, "$") ) )
{ // then strtok failed
perror( "strtok for salt failed" );
continue;
}
// implied else, strtok successful
if( NULL == (hash = strtok(NULL, "\0") ) )
{ // then strtok failed
perror( "strtok for hash failed" );
continue;
}
// implied else, strtok successful
snprintf(buf, sizeof(buf), "$1$%s$", salt);
if( NULL == (fd2 = fopen("polish.txt", "r") ) )
{ // then fopen failed
perror( "fopen for polish.txt failed" );
fclose(fd1); // cleanup
free(str1);
free(str2);
exit( EXIT_FAILURE );
}
// implied else, fopen successful
while( fgets(word, MAX_WORD_LEN, fd2) )
{
(&word[strlen(word)])[-1] = '\0'; // what last char is being dropped?
key1 = crypt(word, buf);
if(!strncmp(key1, pass, strlen(key1)))
{
printf("OK!, The password is: %s\n\n", word);
break;
}
else
{
printf("Oh No, The password did not match\n\n");
} // end if
} // end while
// prep for next test sequence
fclose( fd2 );
fd2 = NULL;
} // end while
fclose(fd1);
fclose(fd2);
free(str1);
free(str2);
return 0;
} // end function: main