fix a memory management error in linearizeAll in the python binding. a new temporary pool is used on every iteration to keep memory allocation to constant

This commit is contained in:
krasimir
2015-04-27 19:27:11 +00:00
parent c1129e15fa
commit 82eeb3ef2b

View File

@@ -986,7 +986,7 @@ static PyTypeObject pgf_TypeType = {
typedef struct IterObject { typedef struct IterObject {
PyObject_HEAD PyObject_HEAD
PGFObject* grammar; PyObject* source;
PyObject* container; PyObject* container;
GuPool* pool; GuPool* pool;
int max_count; int max_count;
@@ -1037,7 +1037,7 @@ Iter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
IterObject* self = (IterObject *)type->tp_alloc(type, 0); IterObject* self = (IterObject *)type->tp_alloc(type, 0);
if (self != NULL) { if (self != NULL) {
self->grammar = NULL; self->source = NULL;
self->container = NULL; self->container = NULL;
self->pool = NULL; self->pool = NULL;
self->max_count = -1; self->max_count = -1;
@@ -1054,7 +1054,7 @@ Iter_dealloc(IterObject* self)
if (self->pool != NULL) if (self->pool != NULL)
gu_pool_free(self->pool); gu_pool_free(self->pool);
Py_XDECREF(self->grammar); Py_XDECREF(self->source);
Py_XDECREF(self->container); Py_XDECREF(self->container);
@@ -1340,13 +1340,13 @@ Concr_parse(ConcrObject* self, PyObject *args, PyObject *keywds)
return NULL; return NULL;
} }
pyres->grammar = self->grammar; pyres->source = (PyObject*) self->grammar;
Py_XINCREF(pyres->grammar); Py_XINCREF(pyres->source);
GuPool* out_pool = gu_new_pool(); GuPool* out_pool = gu_new_pool();
PyObject* py_pool = PyPool_New(out_pool); PyObject* py_pool = PyPool_New(out_pool);
pyres->container = PyTuple_Pack(2, pyres->grammar, py_pool); pyres->container = PyTuple_Pack(2, pyres->source, py_pool);
Py_DECREF(py_pool); Py_DECREF(py_pool);
pyres->pool = gu_new_pool(); pyres->pool = gu_new_pool();
@@ -1404,8 +1404,8 @@ Concr_complete(ConcrObject* self, PyObject *args, PyObject *keywds)
return NULL; return NULL;
} }
pyres->grammar = self->grammar; pyres->source = (PyObject*) self->grammar;
Py_XINCREF(pyres->grammar); Py_XINCREF(pyres->source);
pyres->container = NULL; pyres->container = NULL;
@@ -1504,88 +1504,95 @@ Concr_linearize(ConcrObject* self, PyObject *args)
static PyObject* static PyObject*
Iter_fetch_linearization(IterObject* self) Iter_fetch_linearization(IterObject* self)
{ {
restart:; GuPool* tmp_pool = gu_local_pool();
GuStringBuf* sbuf = gu_string_buf(self->pool); GuExn* err = gu_new_exn(tmp_pool);
GuOut* out = gu_string_buf_out(sbuf);
GuExn* err = gu_new_exn(self->pool);
PgfCncTree ctree = gu_next(self->res, PgfCncTree, self->pool); restart:;
if (gu_variant_is_null(ctree)) { GuStringBuf* sbuf = gu_string_buf(tmp_pool);
return NULL; GuOut* out = gu_string_buf_out(sbuf);
PgfCncTree ctree = gu_next(self->res, PgfCncTree, tmp_pool);
if (gu_variant_is_null(ctree)) {
gu_pool_free(tmp_pool);
return NULL;
} }
pgf_lzr_wrap_linref(ctree, self->pool); // to reduce tuple of strings to a single string; ctree = pgf_lzr_wrap_linref(ctree, tmp_pool); // to reduce tuple of strings to a single string;
// Linearize the concrete tree as a simple sequence of strings. // Linearize the concrete tree as a simple sequence of strings.
ConcrObject* pyconcr = (ConcrObject*)self->container; ConcrObject* pyconcr = (ConcrObject*)self->container;
pgf_lzr_linearize_simple(pyconcr->concr, ctree, 0, out, err, self->pool); pgf_lzr_linearize_simple(pyconcr->concr, ctree, 0, out, err, tmp_pool);
if (!gu_ok(err)) { if (!gu_ok(err)) {
if (gu_exn_caught(err, PgfLinNonExist)) { if (gu_exn_caught(err, PgfLinNonExist)) {
// encountered nonExist. Unfortunately there // encountered nonExist. Unfortunately there
// might be some output printed already. The // might be some output printed already. The
// right solution should be to use GuStringBuf. // right solution should be to use GuStringBuf.
gu_exn_clear(err); gu_exn_clear(err);
goto restart; goto restart;
} }
else if (gu_exn_caught(err, PgfExn)) { else if (gu_exn_caught(err, PgfExn)) {
GuString msg = (GuString) gu_exn_caught_data(err); GuString msg = (GuString) gu_exn_caught_data(err);
PyErr_SetString(PGFError, msg); PyErr_SetString(PGFError, msg);
return NULL; gu_pool_free(tmp_pool);
} else { return NULL;
PyErr_SetString(PGFError, "The abstract tree cannot be linearized"); } else {
return NULL; PyErr_SetString(PGFError, "The abstract tree cannot be linearized");
} gu_pool_free(tmp_pool);
return NULL;
}
} }
GuString str = gu_string_buf_freeze(sbuf, self->pool);
GuString str = gu_string_buf_freeze(sbuf, tmp_pool);
PyObject* pystr = PyString_FromString(str); PyObject* pystr = PyString_FromString(str);
gu_pool_free(tmp_pool);
return pystr; return pystr;
} }
static PyObject* static PyObject*
Concr_linearizeAll(ConcrObject* self, PyObject *args, PyObject *keywds) Concr_linearizeAll(ConcrObject* self, PyObject *args, PyObject *keywds)
{ {
static char *kwlist[] = {"expression", "n", NULL}; static char *kwlist[] = {"expression", "n", NULL};
ExprObject* pyexpr = NULL; ExprObject* pyexpr = NULL;
int max_count = -1; int max_count = -1;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|i", kwlist, if (!PyArg_ParseTupleAndKeywords(args, keywds, "O!|i", kwlist,
&pgf_ExprType, &pyexpr, &max_count)) &pgf_ExprType, &pyexpr, &max_count))
return NULL; return NULL;
GuPool* pool = gu_new_pool(); GuPool* pool = gu_new_pool();
GuExn* err = gu_exn(pool);
GuExn* err = gu_exn(pool);
GuEnum* cts = pgf_lzr_concretize(self->concr, pyexpr->expr, err, pool); GuEnum* cts = pgf_lzr_concretize(self->concr, pyexpr->expr, err, pool);
if (!gu_ok(err)) { if (!gu_ok(err)) {
if (gu_exn_caught(err, PgfExn)) { if (gu_exn_caught(err, PgfExn)) {
GuString msg = (GuString) gu_exn_caught_data(err); GuString msg = (GuString) gu_exn_caught_data(err);
PyErr_SetString(PGFError, msg); PyErr_SetString(PGFError, msg);
gu_pool_free(pool); gu_pool_free(pool);
return NULL; return NULL;
} else { } else {
PyErr_SetString(PGFError, "The abstract tree cannot be linearized"); PyErr_SetString(PGFError, "The abstract tree cannot be linearized");
gu_pool_free(pool); gu_pool_free(pool);
return NULL; return NULL;
}
} }
}
IterObject* pyres = (IterObject*) pgf_IterType.tp_alloc(&pgf_IterType, 0); IterObject* pyres = (IterObject*) pgf_IterType.tp_alloc(&pgf_IterType, 0);
if (pyres == NULL) { if (pyres == NULL) {
gu_pool_free(pool); gu_pool_free(pool);
return NULL; return NULL;
} }
pyres->grammar = self->grammar; pyres->source = (PyObject*)pyexpr;
Py_XINCREF(pyres->grammar); Py_INCREF(pyres->source);
pyres->container = (PyObject*)self; pyres->container = (PyObject*)self;
Py_INCREF(pyres->container); Py_INCREF(pyres->container);
pyres->pool = pool; pyres->pool = pool;
pyres->max_count = max_count; pyres->max_count = max_count;
pyres->counter = 0; pyres->counter = 0;
pyres->fetch = Iter_fetch_linearization; pyres->fetch = Iter_fetch_linearization;
pyres->res = cts; pyres->res = cts;
return (PyObject*)pyres; return (PyObject*)pyres;
} }
static PyObject* static PyObject*
@@ -2042,8 +2049,8 @@ Concr_fullFormLexicon(ConcrObject* self, PyObject *args)
if (pyres == NULL) if (pyres == NULL)
return NULL; return NULL;
pyres->grammar = self->grammar; pyres->source = (PyObject*) self->grammar;
Py_XINCREF(pyres->grammar); Py_XINCREF(pyres->source);
pyres->container = NULL; pyres->container = NULL;
pyres->pool = gu_new_pool(); pyres->pool = gu_new_pool();
@@ -2474,7 +2481,7 @@ PGF_generateAll(PGFObject* self, PyObject *args, PyObject *keywds)
return NULL; return NULL;
} }
pyres->grammar = self; pyres->source = (PyObject*) self;
Py_INCREF(self); Py_INCREF(self);
pyres->pool = gu_new_pool(); pyres->pool = gu_new_pool();