#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% уверены, что были ошибки).
Что вы можете сделать, чтобы исправить это, это одно из следующих:
- распределите его динамически:
char *str = (char*)malloc(sizeof(char)*25);
- измените его на br массив:
char str[25];
- укажите на существующий массив:
char arr[25]; char *str = arr;
Комментарии:
1. Приведение не требуется. Подумайте
str = malloc(sizeof *str * 25)
о том, чтобы избежать неправильного сопоставления типа.2. Честно говоря, мой компилятор не выдал никаких ошибок. Я использую GCC (MinGW).