forked from GitHub/gf-core
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:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user