Segfault при указании функции на структуру

#c #gcc #c99 #gcc9

Вопрос:

У меня есть функция, которая выглядит так:

 int lexWhitespace(TokenizerOutput* input) {

    printf("he");
    if (!(14 > input->toStillParse[0] > 8) amp;amp; !(input->toStillParse[0] == 32)) {
        // checks if the first character in the toStillParse section of input is whitespace.
        return -1;
    } else {input->tokenizerOutput[0] = input->toStillParse[0];}



    for (int i = 1; ; i  ) {
        if ((14 > input->toStillParse[0] > 8) || (input->toStillParse[0] == 32)) {
        // checks if the first character in the toStillParse section of input is whitespace.
            input->tokenizerOutput[i] = input->toStillParse[i];
        } else {return 0;}
    }
}
 

это включает в себя эту структуру:

 struct TokenizerOutput {
    const char* toStillParse; // holds the text that still needs to be parsed.
    char* tokenizerOutput; // holds the text that was just output by tokenizer function.
};
typedef struct TokenizerOutput TokenizerOutput;
 

Когда я пытаюсь вызвать его в основной функции, как это:

 int main(void) {
    printf("hellon");

    TokenizerOutput j = {"        k", " "};

    printf("%sn", (amp;j)->toStillParse);

    lexWhitespace(amp;j);

    return 0;
}
 

Я получаю сегфолт. Segfault происходит до того, как функция lexWhitespace вообще что-либо запускает, потому что она не печатает «он». Я понятия не имею, почему это происходит. Любая помощь была бы очень признательна. Я использую gcc 9.3.0.

Комментарии:

1. Строковые литералы, как правило, недоступны для записи. Вы получите ту же ошибку с char *x = " "; x[0] = 'a';

2. изменить printf("he"); на printf("hen"); fflush(stdout);

Ответ №1:

В этом коде есть некоторые ошибки.

Во-первых, это условие:

 14 > input->toStillParse[0] > 8
 

Это, вероятно, непреднамеренно. Вероятно, это должно быть написано как:

 14 > input->toStillParse[0] amp;amp; input->toStillParse[0] > 8
 

Во-вторых, этот цикл может никогда не завершиться:

 for (int i = 1; ; i  ) {
    if ((14 > input->toStillParse[0] > 8) || (input->toStillParse[0] == 32)) {
    // checks if the first character in the toStillParse section of input is whitespace.
        input->tokenizerOutput[i] = input->toStillParse[i];
    } else {return 0;}
}
 

Обратите внимание, что сравниваемый символ, toStillParse[0] , является одним и тем же символом на каждой итерации цикла. Таким образом, этот цикл либо завершится немедленно, либо будет продолжаться вечно (и, вероятно, произойдет сбой / segfault). Похоже [0] , так и должно быть [i] . Также обратите внимание, что условие, вероятно, написано неправильно.

В C, x > y > z это не то же самое, что x > y amp;amp; y > z . Всякий раз , когда вы видите x > y > z , это, вероятно, неправильно (если только вы не просматриваете записи IOCCC или что-то в этом роде).

Комментарии:

1. Это забавно. Я еще не совсем дошел до этой части. Спасибо!