Почему моя программа вылетает, когда я объявляю эти две переменные?

#c #variables #interpreter

#c #переменные #интерпретатор

Вопрос:

Я пытаюсь создать интерпретатор, используя язык программирования C, он работает хорошо, но когда я пытаюсь добавить эти две переменные в код, программа просто вылетает. К счастью, когда я добавляю ключевое слово static или оставляю переменные глобальными в программе, программа не вылетает. Почему это происходит? Вот код:

 #include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <windows.h>

//If I leave the variables here the program doesn't crash
//int esMain = 0;
//int esEnd = 0;

int main(int argc, char** argv){
FILE *f;

f = fopen(argv[1], "r ");


if(f == NULL){
    perror("Error: No se encuentra el archivonDescripcion");
    exit(1);
}

if(ferror(f)){
    printf("Archivo corrupto");
    exit(1);
}

printf("nEjecutando archivo: %snnn", argv[1]);



int esMain = 0;//These two variables makes the program to crash
int esEnd = 0;

//But if I add the static keyword in both variables the program works well.

char* str;

while(1){

    fgets(str, 25, f);

    if(strncmp(str, "MAIN:", 5) == 0){
            esMain = 1;
    }

    if(strncmp(str, "END.", 4) == 0){
            esEnd = 1;
    }

    if(feof(f) != 0){
        if(esMain == 0){
            printf("No existe el parametro main, cierre por no tener el parametro main (poner MAIN: ENCIMA)");
            exit(1);
        }
        if(esEnd == 0){
            printf("No existe el parametro end, cierre por no tener el parametro main (poner END. ENCIMA)");
            exit(1);
        }
        break;
    }
}

rewind(f);

while(1){
    fgets(str, 500, f);

    if(strncmp(str, "print ", 6) == 0){
        printf(str   6);
    }

    if(strncmp(str, "msg", 3) == 0){
        if(strstr(str   4, "check")){
            MessageBox(HWND_DESKTOP, str   10, "Check", MB_ICONINFORMATION);
        }

        if(strstr(str   4, "error")){
            MessageBox(HWND_DESKTOP, str   10, "Error", MB_ICONERROR);
        }
    }

    if(strncmp(str, "pause", 5) == 0){
        getch();
    }

    if(feof(f) != 0){
        break;
    }


}

printf("nnnEND EXECUTION");

fclose(f);

return 0;
}
 

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

1. char* str; Это неинициализированный указатель, который не указывает никуда конкретно, но fgets(str, 25, f); пытается записать в него, что является неопределенным поведением . Перед str его использованием укажите допустимый строковый буфер, например char str[25]; , или char *str = malloc(25); .

2. если вы выбираете путь динамического выделения памяти с помощью malloc , не забудьте также free(str) в конце программы, вы также можете захотеть привести возвращаемое значение malloc к char* , поскольку по стандарту оно возвращает void*

3. Включите предупреждения компилятора, чтобы помочь поймать эти простые ошибки.

4. if(feof(f) != 0){ слишком поздно. Используйте while(fgets(str, 500, f)) {

5. printf(str 6); это благодатная почва для хакерского эксплойта, поскольку printf() сначала ожидается строка формата . Используйте printf("%s", str 6);

Ответ №1:

char* str; Объявление, вероятно, нарушает ваш код. Когда вы объявляете его как глобальный, он хранится в другом месте в памяти, чем если бы вы объявили его внутри функции.

Вам повезло, что ваша программа работает с ней как с глобальной переменной. Поскольку вы не зарезервировали какое-либо место в памяти, переменная обращается к некоторой памяти, которой она не должна (неопределенное поведение). «Повезло» может быть не лучшим словом для описания, потому что из-за его неопределенного поведения вы можете подумать, что ваша программа работает правильно, а это не так (если бы она разбилась, вы были бы на 100% уверены, что были ошибки).

Что вы можете сделать, чтобы исправить это, это одно из следующих:

  1. распределите его динамически: char *str = (char*)malloc(sizeof(char)*25);
  2. измените его на br массив: char str[25];
  3. укажите на существующий массив: char arr[25]; char *str = arr;

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

1. Приведение не требуется. Подумайте str = malloc(sizeof *str * 25) о том, чтобы избежать неправильного сопоставления типа.

2. Честно говоря, мой компилятор не выдал никаких ошибок. Я использую GCC (MinGW).