مشكلة في إنشاء Shell في C (Seg-Fault وferror)
-
13-12-2019 - |
سؤال
لقد كنت أتابع برنامجًا تعليميًا حول كيفية صنع الصدفة الخاصة بي ولكنني عالقة منذ بضعة أيام.
شيئان:
- عندما يتم تجميع هذا الرمز وتشغيله، سيكون به أخطاء تجزئة بشكل عشوائي ولا أستطيع معرفة السبب.
- يبدو أن عبارة if `if (ferror != 0)` صحيحة دائمًا.وهو أمر غريب لأنني لا أفهم السبب فجيتس () يفشل في رئيسي() وظيفة.
أي معلومات حول هذه المواضيع (أو مواضيع أخرى حول إنشاء هذه الصدفة) ستكون موضع تقدير كبير.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#define MAXSIZE 512
int parseCmd(char *cmd, char *args[])
{
printf("LOGGER: parseCmd(cmd=%s, args=%p)\n", cmd, args);
char cmdDelims[] = {' ','>'};
char *cmdReader;
cmdReader = strtok(cmd, cmdDelims);
int i = 0;
while (cmdReader != NULL)
{
args[i] = strdup(cmdReader);
printf("LOGGER: args[%d]=%s\n", i, args[i]);
cmdReader = strtok(NULL, cmdDelims);
i++;
}
return 0;
}
void printToLine(char *args[])
{
int length;
length = sizeof(args) / sizeof(char);
int i = 0;
while (i < length)
{
printf("%s\n", args[i]);
i++;
}
}
int main(int argc, char *argv[])
{
char *in;
in = malloc(MAXSIZE);
char *args[15];
char *cmd = NULL;
int errorBit = 0;
int terminationBit = 1;
char error_message[30] = "An error has occurred\n";
char inDelims[] = "\n";
while (terminationBit)
{
printf("mysh>");
// get input from command line
fgets(in, MAXSIZE, stdin);
if (ferror != 0)
{
perror(error_message);
}
// get pointer to command line input w/o the newline
cmd = strtok(in, inDelims);
// parse the command into separate arguments
errorBit = parseCmd(cmd, args);
if (errorBit)
{
perror(error_message);
exit(1);
}
printToLine(args);
// check if the user wants to exit the shell
if (strcmp(*args, "exit") == 0)
{
terminationBit = 0;
}
}
return 0;
}
فيما يلي بعض المخرجات:
**[ray@12] (6)$ mysh**
mysh>1 2 3
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3, args=0x7fff4a50b080)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
1
2
3
Segmentation fault (core dumped)
**[ray@12] (7)$ mysh**
mysh>1 2 3 4 5 6 7 8 9 10
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3 4 5 6 7 8 9 10, args=0x7fffba053d70)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
LOGGER: args[3]=4
LOGGER: args[4]=5
LOGGER: args[5]=6
LOGGER: args[6]=7
LOGGER: args[7]=8
LOGGER: args[8]=9
LOGGER: args[9]=10
1
2
3
4
5
6
7
8
mysh>1 2 3
An error has occurred
: Success
LOGGER: parseCmd(cmd=1 2 3, args=0x7fffba053d70)
LOGGER: args[0]=1
LOGGER: args[1]=2
LOGGER: args[2]=3
1
2
3
4
5
6
7
8
المحلول
ل ferror
خطأ، تحتاج إلى اختبار ferror(stdin)
, ، لا ferror
.الأخير هو عنوان الوظيفة، والذي لن يكون صفرًا أبدًا:
if (ferror(stdin) != 0)
{
perror(error_message);
}
بالنسبة لبعض الأخطاء على الأقل، فإن هذا لا يفعل ما تعتقده:
length = sizeof(args) / sizeof(char);
هذا سوف يخبرك كم عدد البايتات المستخدمة لتخزين المؤشر, ، وهو 4 أو 8 حسب، و لا عدد الحجج.
لذا، إذا كان لديك أربع (أو ثماني) وسيطات، فستكون كذلك يظهر للعمل.إذا كان لديك المزيد، فسيبدو أنك تتجاهل بعض الحجج.وإذا كان لديك أقل، فسوف يجلب الوسيطات المفقودة عبر الفراغ، مما يؤدي إلى خطأ تجزئة (مؤكد تقريبًا).
تحتاج إلى الحساب length
بشكل مستقل وتمريرها أو تخزين بعض أدوات الإنهاء فيها args
, ، على سبيل المثال إضافة وسيطة NULL بعد آخر وسيطة صالحة تجدها:
cmdReader = strtok(NULL, cmdDelims);
i++;
}
args[i] = NULL;
return 0;
}
void printToLine(char *args[])
{
int i = 0;
while (args[i])
{
printf("%s\n", args[i]);
i++;
}
}