2012-03-30 3 views
0

Iam пытается скомпилировать файл в следующем формате, сделав парсер в бизонеНеобъяснимое значения нежелательного в переменной

LOCATION house 
NAME "House" 
DESCRIPTION "You are standing\nin front of your house.\nPaths lead towards east and west." 
east flag 
west forest 

LOCATION obelisk 
NAME "Obelisk" 
DESCRIPTION "A big obelisk is\nstanding before you. You can either go east or west or south." 
south flag 
east flag 
west treasure 

Моего парсера имеет функцию

int find(char *id) { 
int i; 
for(i=0;i<nLoc;i++) { 
if(strcmp(id,tmp_idList[i]) == 0){ 
    printf(tmp_idList[0]); 
    printf(" i = %d returned",i); 
return i; 

    } 
} 

printf("Copying..."); 
strcpy(tmp_idList[nLoc],id); 
printf("%d %s",nLoc,tmp_idList[nLoc]); 
nLoc++; 
printf(" nloc-1 = %d returned",nLoc-1); 
return (nLoc-1); 
} 

Он использует

char tmp_idList[60][100]; 

Грамматика (применимо здесь)

locnSpec : tok_LOCN tok_IDENT nameSpec descrSpec exitList 
      {int k = find($2); 
      locList[k].name = strdup(tmp_name); 
      locList[k].descr = strdup(tmp_descr); 
      memcpy(locList[k].exits, 
        tmp_exit, 
        4*sizeof(int));} 

Теперь, когда я запускаю этот код, как-то

tmpidList[0] 

становится населенным со значением нежелательного, как показано ниже на выходе

Microsoft Windows [Version 6.1.7600] 
Copyright (c) 2009 Microsoft Corporation. All rights reserved. 



C:\Users\MY PC\Desktop\final>bison -d -o compile.c adv6.y 

C:\Users\MY PC\Desktop\final>gcc -o compile compile.c lex.yy.c 

C:\Users\MY PC\Desktop\final>compile<toy.al 



Copying...0 flag nloc-1 = 0 returned 
Copying...1 forest nloc-1 = 1 returned 

Copying...2 house nloc-1 = 2 returned 


flag i = 0 returned // OK HERE 
flag i = 0 returned 
Copying...3 treasure nloc-1 = 3 returned 

Copying...4 obelisk nloc-1 = 4 returned 



Copying...5 marsh nloc-1 = 5 returned 


nd west. i = 4 returned // JUNK HERE 
Copying...6 flag nloc-1 = 6 returned 
nd west. i = 1 returned 

nd west. i = 3 returned 


t. i = 4 returned 
t. i = 2 returned 
t. i = 4 returned 

t. i = 6 returned 


t. i = 5 returned 
t. i = 2 returned 
t. i = 3 returned 

t. i = 1 returned t. i = 2 returned 


C:\Users\MY PC\Desktop\final> 

как сигнал, когда я попытался выделение памяти с помощью таНоса

char* tmp_idList[20] 

... 

tmp_idList[nLoc] = malloc(strlen(id) +1) 

он работал нормально, пока флаг не был в tmp_idList [0], но прекратил работу и ере была ошибка памяти в файле compile.exe.

Кто-нибудь знает, что происходит? если вы хотите получить дополнительную информацию, я могу предоставить. Мне действительно нужна помощь для моего проекта в колледже.

+0

Используйте * string * Класс C++ вместо * char ** – m0skit0

+0

В качестве альтернативы не помещайте вопрос о c с помощью [C++]. – dmckee

+0

Я удалил тег C++; это казалось артефактом коллективно подсознательного мифического языка под названием «C/C++». – aib

ответ

1

1 примечание. Функцию find можно назвать intern. То, что он делает, сводит токен строки к числовому атому. Если он раньше не видел строку, он возвращает новый атом, но если он дважды вызывается с той же строкой, он возвращает один и тот же атом каждый раз. Это называется интернированием, которое возникло на языке Lisp.

У вас есть некоторые проблемы в этом коде, так как ваши символы имеют пространство для 100 имен символов, но вы не проверяете это и просто используете blind strcpy.

Теперь об этом правиле грамматики:

locnSpec: tok_LOCN tok_IDENT nameSpec descrSpec exitList {INT к = найти (2 $); locList [k] .name = strdup (tmp_name); locList [k] .descr = strdup (tmp_descr); тетсру (locList [K] .exits, tmp_exit, 4 * SizeOf (INT));}

Что делать, если место спецификации происходит дважды за одно место? Вы просто просачиваете эту память, перезаписывая locList[k].name. Вы можете захотеть освободить прежнее значение, которое было там раньше. Если эти структуры инициализированы нулем/нулями, вы можете сделать это:

free (locList [k] .name); locList [k].name = strdup (tmp_name);

Во-вторых, где эти переменные tmp_name и tmp_descr? Являются ли эти глобалы, наполненные значениями во время сокращения 0терминальных символов namesSpec и descrSpec?

Это неприятный подход; вы действительно должны использовать стек Yacc для возврата семантических значений и ссылаться на них через $ 3, $ 4 и $ 5.

Что касается проблемы коррупции, которую вы преследуете; это, скорее всего, переполнение статического массива. Вы ничего не проверяете.

Суть проблемы заключается в следующем:

/* two arrays, probably located side by side in the executable image */ 
static char array1[20][30]; 
static char array2[40][20]; 

Если доступ array1 за пределы его конца, вы, скорее всего, мусор какой-либо другой переменной, как, возможно, array2, в зависимости от того, как вещи раскладывают в RUN- время.

Одна вещь, которую вы можете сделать, в случае отсутствия более совершенных средств отладки, - это выполнить код в отладчике и контролировать содержимое перезаписываемой переменной. Попытайтесь поймать программу «red handed», изменив это значение.

Во-вторых, содержимое этого решетчатого массива должно дать вам представление о том, откуда появился этот материал! Это фрагмент текста, который можно проследить до вашего ввода, и оттуда вы можете отслеживать, где эта часть ввода обрабатывается в вашей синтаксической машине.

+0

Теперь я понимаю проблему. Я попытаюсь исправить это. Я как-то уменьшил размер строк и заставил его работать, но я отлажу его по-своему. Спасибо большое :) – YuNo

0

Попробуйте с

tmp_idList = malloc(strlen(id) +1) 

Кроме того, я предлагаю вам с помощью C++ строка класс вместо обугленного *. Это больше подвержено ошибкам для новичков, которые не полностью понимают C-указатели и распределение памяти (что похоже на вас).

+0

Нет, это не сработает. Это несовместимое задание. – YuNo

+0

Я не думаю, что могу использовать строки C++, потому что bison генерирует файл c – YuNo