سؤال

لقد كنت أتابع برنامجًا تعليميًا حول كيفية صنع الصدفة الخاصة بي ولكنني عالقة منذ بضعة أيام.

شيئان:

  1. عندما يتم تجميع هذا الرمز وتشغيله، سيكون به أخطاء تجزئة بشكل عشوائي ولا أستطيع معرفة السبب.
  2. يبدو أن عبارة 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++;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top