[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: memory leak
From: |
Hans Aberg |
Subject: |
Re: memory leak |
Date: |
Tue, 2 May 2006 13:20:45 +0200 |
On 2 May 2006, at 09:48, Akim Demaille wrote:
Le 29 avr. 06 à 19:16, Hans Aberg a écrit :
You do not give much info about what is leaking, so it could just
as well be in your actions. The Bison generated parser used to
leak for various strings that had not been translated from the C-
subset of C++ to say using std::string, but I am not sure about
the matter nowadays.
Can you detail please? For instance a pointer to the mailing
list archive referring to this.
I believe you use to say "read the @$#% code" or something. :-)
Nevertheless, I only know about the stuff from my own C++ skeleton,
unable to use later Bison. Then, after the "switch" statement of the
generated parser, I have the stuff below. I have a vague memory that
the C stuff that I translated into C++ used to leak. Specifically, I
think it was the string I have named "message", which is of C++ type
std::string, that in the C version was something that was not
properly deallocated. Perhaps it has changed in later Bison versions.
state_stack_.erase(state_stack_.end() - rule_length_,
state_stack_.end());
semantic_stack_.erase(semantic_stack_.end() - rule_length_,
semantic_stack_.end());
#if YYLSP_NEEDED
location_stack_.erase(location_stack_.end() - rule_length_,
location_stack_.end());
#endif
#if YYDEBUG
if (do_debug_) {
YYCDEBUG << "state stack now";
for (state_stack::const_iterator i = state_stack_.begin();
i != state_stack_.end(); ++i)
YYCDEBUG << ' ' << *i;
YYCDEBUG << std::endl;
}
#endif
semantic_stack_.push_back(yyval);
#if YYLSP_NEEDED
location_stack_.push_back(yyloc);
#endif
// Shift the result of the reduction.
n_ = r1_[n_];
state_ = pgoto_[n_ - ntokens_] + state_stack_.back();
if (state_ >= 0 && state_ <= last_ && check_[state_] ==
state_stack_.back())
state_ = table_[state_];
else
state_ = defgoto_[n_ - ntokens_];
goto yynewstate;
// Report and recover from errors. This is very incomplete.
yyerrlab:
// If not already recovering from an error, report this error.
if (!errstatus) {
++nerrs;
#if YYERROR_VERBOSE
n_ = pact_[state_];
if (pact_ninf_ < n_ && n_ < last_) {
message = "parse error, unexpected ";
message += name_[ilooka_];
int count = 0;
for (int x = (n_ < 0 ? -n_ : 0); x < ntokens_ + nnts_; ++x)
if (check_[x + n_] == x && x != terror_)
++count;
if (count < 5) {
count = 0;
for (int x = (n_ < 0 ? -n_ : 0); x < ntokens_ + nnts_; ++x)
if (check_[x + n_] == x && x != terror_) {
message += (!count++) ? ", expecting " : " or ";
message += name_[x];
}
}
}
else
#endif
message = "parse error";
#if 1
yyerror(message);
#else
error_();
#endif
}
goto yyerrlab1;
// Error raised explicitly by an action.
yyerrlab1:
if (errstatus == 3) {
/* If just tried and failed to reuse lookahead token after an
error, discard it. */
/* Return failure if at end of input. */
if (lookahead_ == eof_)
goto yyabortlab;
YYCDEBUG << "Discarding token " << lookahead_
<< " (" << name_[ilooka_] << ")." << std::endl;
lookahead_ = empty_;
}
/* Else will try to reuse lookahead token after shifting the error
token. */
errstatus = 3;
for (;;) {
n_ = pact_[state_];
if (n_ != pact_ninf_) {
n_ += terror_;
if (0 <= n_ && n_ <= last_ && check_[n_] == terror_) {
n_ = table_[n_];
if (0 < n_)
break;
}
}
/* Pop the current state because it cannot handle the error
token. */
if (state_stack_.empty())
goto yyabortlab;
#if YYDEBUG
if (do_debug_) {
if (stos_[state_] < ntokens_) {
YYCDEBUG << "Error: popping token "
<< token_number_[stos_[state_]]
<< " (" << name_[stos_[state_]];
# ifdef YYPRINT
YYPRINT(stderr, token_number_[stos_[state_]],
semantic_stack_.top());
# endif
YYCDEBUG << ')' << std::endl;
}
else {
YYCDEBUG << "Error: popping nonterminal ("
<< name_[stos_[state_]] << ')' << std::endl;
}
}
#endif
state_ = (state_stack_.pop_back(), state_stack_.back());
semantic_stack_.pop_back();
#if YYLSP_NEEDED
location_stack_.pop_back();
#endif
#if YYDEBUG
if (do_debug_) {
YYCDEBUG << "Error: state stack now";
for (state_stack::const_iterator i = state_stack_.begin();
i != state_stack_.end(); ++i)
YYCDEBUG << ' ' << *i;
YYCDEBUG << std::endl;
}
#endif
}
if (n_ == final_)
goto yyacceptlab;
YYCDEBUG << "Shifting error token, ";
semantic_stack_.push_back(lookahead_value_);
#if YYLSP_NEEDED
location_stack_.push_back(lookahead_location_);
#endif
state_ = n_;
goto yynewstate;
// Accept.
yyacceptlab:
return 0;
// Abort.
yyabortlab:
return 1;