Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

C++

Войти
Регистрация
Восстановить пароль
 
Aye Aye
367 / 281 / 36
Регистрация: 17.12.2009
Сообщений: 567
#1

BISON, освобождение памяти при синтаксической ошибке. - C++

04.05.2011, 16:14. Просмотров 1026. Ответов 2

Здравствуйте. При работе с BISON, как освободить память выделенную под возвращаемые продукциями "объекты" в случае синтаксической ошибки? Все мануалы облазил (штук 5-6) не нашел ничего кроме описания зачем нужен токен error и yyerrok и все такое.
Вот составил пример, чтобы вопрос был ясен и было на чем показать. В нем надо как-то, в продукции line строка 36, освободить память, занятую деревом, если произошла ошибка разбора.
Код
/* Синтаксический анализатор для простых арифметических выражений.  */
%{
#include <stdio.h>
#include <stdlib.h>
#define YYDEBUG 1
static int yylex(void);
static int yyerror(char*);

float variable;

typedef struct tree {
  struct tree *left;
  struct tree *right;
  float val;
  int op;
} tree;
#define YYSTYPE tree*
tree *make_tree(tree *l, tree *r, float v, int o);
void print_tree(tree *t);
void free_tree(tree *t);
%}

%token NUM
%left '+' '-'
%left '/' '*'
%left UNARY
%left '('

%%
input:
    line                 { print_tree($1); free_tree($1); }
  | input line           { print_tree($2); free_tree($2); }
  ;
line:
    exp '\n'             { $$ = $1; }
  | error '\n'           { /* Тут надо освободить память. */ }
  ;
exp:
    prim
  | exp '+' exp          { $$ = make_tree($1, $3, 0, '+'); }
  | exp '-' exp          { $$ = make_tree($1, $3, 0, '-'); }
  | exp '*' exp          { $$ = make_tree($1, $3, 0, '*'); }
  | exp '/' exp          { $$ = make_tree($1, $3, 0, '/'); }
  ;
prim:
    '(' exp ')'          { $$ = $2; }
  | '-' prim %prec UNARY { $$ = make_tree($2, NULL, 0, 'u'); }
  | NUM                  { $$ = make_tree(NULL, NULL, variable, 'v'); }
  ;
%%
tree *make_tree(tree *l, tree *r, float v, int o)
{
  tree* t = (tree*)malloc(sizeof(tree));
  t->left = l;
  t->right = r;
  t->val = v;
  t->op = o;
  return t;
}
void print_tree(tree *t)
{
  static n = 0;
  if (t != NULL) {
    int i;
    for (i = 0; i < n; i++)
      printf(" ");
    switch(t->op) {
    case 'u': printf("- unary\n"); break;
    case 'v': printf("%f\n", t->val); break;
    default:
      printf("%c\n", t->op);
    }
    n++;
    print_tree(t->left);
    print_tree(t->right);
    n--;
  }
}
void free_tree(tree *t)
{
  if (t != NULL) {
    free_tree(t->left);
    free_tree(t->right);
    free(t);
  }
}
int yylex()
{
  int c;
  while (!feof(stdin) && (c = getc(stdin)) == ' ');
  if (feof(stdin)) return 0;
  switch (c) {
  case '+':
  case '-':
  case '*':
  case '/':
  case '(':
  case ')':
  case '\n':
        return c;
  default:
    break;
  }
  if (isdigit(c)) {
    ungetc(c, stdin);
    fscanf(stdin, "%f", &variable);
    return NUM;
  }
}

int yyerror(char *s)
{
  fprintf(stderr, "%s.\n", s);
  return 1;
}
int main()
{
  /* yydebug = 1; */
  return yyparse();
}
Единственная моя идея: сделать стек с указателями на узлы дерева, и при появлении токена error все эти указатели освобождать. Но это плохой вариант, слишком много лишнего кода. Пример выше - всего лишь пример, есть "реальная программа" для построения синтаксического дерева для исходника на C, и там время работы критично, мне кажется... Нет ли у BISON какого-нибудь "родного" способа освободить память? Собственным стеком бизона yyvs пользоваться не получается ошибка сегментирования или ноль реакции на print_tree и free_tree.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.05.2011, 16:14
Здравствуйте! Я подобрал для вас темы с ответами на вопрос BISON, освобождение памяти при синтаксической ошибке. (C++):

Освобождение памяти после std:bind - C++
Что имею: - CentOS - gcc 4.8 - valgrind Что делаю - С помощью valgrind устраняю утечки - Если приложение остановлено...

Очень долгое освобождение динамически выделенной памяти - C++
Все никак не могу разобраться с одной проблеммой! У меня есть отображение, в котором хранятся указатели на абстрактный класс Node ...

Корректное освобождение памяти при принудительном завершении потока TThread - C++ Builder
У меня в отдельном потоке выполняются некоторые вычисления. В процессе выполнения этой функции создаются и удаляются различные объекты....

Освобождение памяти - C++ Builder
//--------------------------------------------------------------------------- #ifndef Lariphm_H #define Lariphm_H /* *...

Автоматическое освобождение памяти - C++ Builder
Вот небольшой тестовый примерчик. Это программа, выделяющая для работы 1ГБ памяти. *.h: ...

Освобождение памяти для дерева - C++ Builder
struct Node { char tfield; Node *son; Node *brother; Node *parent; }; написал так: ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
dev001
36 / 36 / 3
Регистрация: 13.05.2010
Сообщений: 70
09.12.2011, 16:35 #2
в функцию yyparse можно передать параметр при вызове.
и что если вместо malloc использовать обвертку, в которой будет вызываться память использую контролирующий объект

т.е

C
1
yyparse( NULL, MyObject );
и
C
1
2
3
4
5
6
7
8
9
tree *make_tree(SomeObject *MyObject, tree *l, tree *r, float v, int o)
{
  tree* t = (tree*)tree_alloc(MyObject->tree_heap, sizeof(tree));
  t->left = l;
  t->right = r;
  t->val = v;
  t->op = o;
  return t;
}

да и не забыть объявить #define YYPARSE_PARAM dummy, SomeObject *MyObject
и собрать с ключом %pure_parser (может и без него)

Тогда ваш общий объект будет доступен как доп параметр во все функции.
0
Qazan
211 / 59 / 9
Регистрация: 30.04.2013
Сообщений: 797
Записей в блоге: 10
04.03.2016, 16:34 #3
Aye Aye, лучше поздно, чем никогда

сделайте в вашей структуре метод delete , который в себе бы вызывал методы delete потомков.
C
1
2
3
4
5
6
7
8
9
10
11
struct A {
  A* left;
  A *right;
 
  void delete {
     left->delete();
     right->delete();
     free(left);
     free(right);
  }
};
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.03.2016, 16:34
Привет! Вот еще темы с ответами:

Освобождение памяти контейнерами STL - C++ Builder
Подскажите как это сделать в С++ Builder. Есть класс: class Test { public: int num; string str; ...

Удаление объекта (освобождение памяти) - C++ Builder
Здравствуйте все! Имеется следующий код: TForm1* Form1 = new TForm1(); void* form = Form1; delete form; Вопрос: удаление...

Освобождение памяти других приложений - C++ Builder
Доброго вечера)Заметил много интересных утилит которые высвобождают память из различные процессов. Есть замечательная функция: bool...

Освобождение памяти динамического массива - C++ Builder
всем привет =) есть такой массив, создаю его динамически: AgrType **Points = new AgrType*; for (i = 0; i &lt; 3; i++) { Points = new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru