[英]Segmentation fault core dumped when reading file
我在第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文件)。 有人可以看看嗎?
從代碼中的許多問題中,最重要的是
你並不需要強制轉換 malloc
,這是沒有必要的,並可能導致無法跟蹤的錯誤。
你並不需要使用 malloc
固定大小的局部變量。
您永遠不會檢查任何在失敗時返回NULL
的函數的返回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
循環,但你fopen()
這里面,你可能fopen
很多倍主編它比你fclose
ð它。
您有兩個選擇,或者將fclose()
移到while
循環內,或者將fopen()
移到while
循環外,第二個當然更好。
這是錯誤的,因為您增加了指向同一字符串的指針,因此必須這樣做,讀取strtok()
strtok(NULL, "$");
如您所見,您有很多潛在的未定義行為,尤其是在代碼中取消引用NULL
指針時,如果要防止SEGMENTATION FAULT
,則應修復所有這些問題。
看到程序員忽略這些事情是很普遍的,但是您應該通過小心確保程序不會崩潰。
NULL
,否則檢查每個取消引用的指針。 NULL
,這樣可以確保如果還沒有指向任何指針,則為NULL
,然后可以進行檢查。 處理指針是一件非常困難的事情,但是一旦養成了這些好習慣,就永遠不會再有愚蠢的bug了-> 好吧,幾乎永遠不會 !
C沒有像Java這樣的異常機制。 獲取有關錯誤的信息的唯一方法是檢查從函數返回的值,有時還獲得更多信息errno
。
在您的代碼中,您應該檢查fopen
成功,如果不成功則返回錯誤信息。
您的程序崩潰是因為您可能嘗試讀取您沒有讀取權限的文件,並且由於fopen
返回NULL
。 修補程序是作為root或sudo
運行程序。
編輯
我試了一下,您的程序崩潰了:
程序收到信號SIGSEGV,分段故障。 _IO_fgets(buf = 0x7fffffffd6a0“”,n = 200,fp = 0x0)位於iofgets.c:50 50 iofgets.c:無此類文件或目錄。
因為添加時沒有波蘭語.txt ,所以運行平穩,沒有錯誤
問題是此行缺少錯誤檢查:
fd1 = fopen(argv[1], "r");
fopen()
返回指向已填充的FILE
對象的指針,如果無法打開文件(該文件不存在,或者用戶沒有足夠的權限讀取該文件fopen()
返回 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行崩潰的原因。
// 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.