Необъяснимое значение барахла в переменной - PullRequest
0 голосов
/ 30 марта 2012

Я пытаюсь скомпилировать файл следующего формата, сделав парсер в зубре

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>

В качестве подсказки, когда я пытался выделить память через malloc

char* tmp_idList[20]

...

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

, он работал нормально, пока флаг не был в tmp_idList [0], но перестал работать и во время компиляции произошла ошибка памяти.Отлично.

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

Ответы [ 2 ]

1 голос
/ 01 апреля 2012

Одна нота.Ваша функция find может называться intern.Что он делает, так это уменьшает строковый токен до числового атома.Если он не видел строку ранее, он возвращает новый атом, но если он вызывается дважды с одной и той же строкой, он возвращает один и тот же атом каждый раз.Это называется интернированием, которое возникло на языке Lisp.

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

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

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));}

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

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

Во-вторых, откуда берутся эти tmp_name и tmp_descr переменные?Являются ли эти глобалы наполненными значениями во время сокращения нетерминальных символов 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, в зависимости от того, как все расположено в образе времени выполнения.

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

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

0 голосов
/ 30 марта 2012

Попробуйте с

tmp_idList = malloc(strlen(id) +1 )

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

...