aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormescalinum <mescalinum@users.sourceforge.net>2009-09-12 20:28:39 +0000
committermescalinum <mescalinum@users.sourceforge.net>2009-09-12 20:28:39 +0000
commit7b4b78fc1a3ff3847109750a66c981254ac865dc (patch)
tree8370aa29baba5c084579c590bb615f5cb47d34e5
parent1d76e546322b5dff03b37173f96b1e12907ce880 (diff)
solve the evil memory leak
svn path=/trunk/externals/tclpd/; revision=12319
-rw-r--r--tcl_class.cxx75
-rw-r--r--tcl_extras.h2
-rw-r--r--tcl_widgetbehavior.cxx34
3 files changed, 87 insertions, 24 deletions
diff --git a/tcl_class.cxx b/tcl_class.cxx
index bd583a9..01aebaf 100644
--- a/tcl_class.cxx
+++ b/tcl_class.cxx
@@ -37,35 +37,56 @@ t_class* tclpd_guiclass_new(const char* name, int flags) {
}
t_tcl* tclpd_new(t_symbol* classsym, int ac, t_atom* at) {
+ // lookup in class table
const char* name = classsym->s_name;
t_class* qlass = class_table[string(name)];
+
t_tcl* self = (t_tcl*)pd_new(qlass);
self->ninlets = 1 /* qlass->c_firstin ??? */;
+
char s[64];
snprintf(s, 64, "tclpd:%s:x%lx", name, objectSequentialId++);
self->self = Tcl_NewStringObj(s, -1);
Tcl_IncrRefCount(self->self);
+
+ // store in object table (for later lookup)
object_table[string(s)] = (t_pd*)self;
- Tcl_Obj *av[ac+2];
+
+ // build constructor command
+ Tcl_Obj *av[ac+2]; InitArray(av, ac+2, NULL);
av[0] = Tcl_NewStringObj(name, -1);
Tcl_IncrRefCount(av[0]);
av[1] = self->self;
+ Tcl_IncrRefCount(av[1]);
for(int i=0; i<ac; i++) {
if(pd_to_tcl(&at[i], &av[2+i]) == TCL_ERROR) {
- tclpd_interp_error(TCL_ERROR);
- pd_free((t_pd*)self);
- return 0;
+#ifdef DEBUG
+ post("pd_to_tcl: tclpd_new: failed during conversion. check memory leaks!");
+#endif
+ goto error;
}
}
if(Tcl_EvalObjv(tcl_for_pd, ac+2, av, 0) != TCL_OK) {
- tclpd_interp_error(TCL_ERROR);
- pd_free((t_pd*)self);
- return 0;
+ goto error;
}
+
+ for(int i = 0; i < (ac+2); i++)
+ Tcl_DecrRefCount(av[i]);
+
return self;
+
+error:
+ tclpd_interp_error(TCL_ERROR);
+ for(int i = 0; i < (ac+2); i++) {
+ if(!av[i]) break;
+ Tcl_DecrRefCount(av[i]);
+ }
+ pd_free((t_pd*)self);
+ return 0;
}
void tclpd_free(t_tcl* self) {
+ Tcl_DecrRefCount(self->self);
#ifdef DEBUG
post("tclpd_free called");
#endif
@@ -76,25 +97,42 @@ void tclpd_anything(t_tcl* self, t_symbol* s, int ac, t_atom* at) {
}
void tclpd_inlet_anything(t_tcl* self, int inlet, t_symbol* s, int ac, t_atom* at) {
-/* proxy method */
- Tcl_Obj* av[ac+3];
+ // proxy method - format: <self> <inlet#> <selector> ...
+ Tcl_Obj* av[ac+3]; InitArray(av, ac+3, NULL);
+ int result;
+
av[0] = self->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewIntObj(inlet);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj(s->s_name, -1);
Tcl_IncrRefCount(av[2]);
for(int i=0; i<ac; i++) {
if(pd_to_tcl(&at[i], &av[3+i]) == TCL_ERROR) {
- tclpd_interp_error(TCL_ERROR);
- return;
+#ifdef DEBUG
+ post("pd_to_tcl: tclpd_inlet_anything: failed during conversion. check memory leaks!");
+#endif
+ goto error;
}
}
- int result = Tcl_EvalObjv(tcl_for_pd, ac+3, av, 0);
- Tcl_DecrRefCount(av[1]);
- Tcl_DecrRefCount(av[2]);
+ result = Tcl_EvalObjv(tcl_for_pd, ac+3, av, 0);
if(result != TCL_OK) {
- tclpd_interp_error(TCL_ERROR);
+ goto error;
+ }
+
+ for(int i=0; i < (ac+3); i++)
+ Tcl_DecrRefCount(av[i]);
+
+ // OK
+ return;
+
+error:
+ tclpd_interp_error(TCL_ERROR);
+ for(int i=0; i < (ac+3); i++) {
+ if(!av[i]) break;
+ Tcl_DecrRefCount(av[i]);
}
+ return;
}
/* Tcl glue: */
@@ -127,9 +165,13 @@ void poststring2 (const char *s) {
}
void tclpd_save(t_gobj* z, t_binbuf* b) {
- Tcl_Obj* av[3], *res;
+ Tcl_Obj* av[3]; InitArray(av, 3, NULL);
+ Tcl_Obj* res;
+
t_tcl* x = (t_tcl*)z;
+
av[0] = x->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewStringObj("object", -1);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("save", -1);
@@ -172,6 +214,7 @@ void tclpd_save(t_gobj* z, t_binbuf* b) {
pd_error(x, "Tcl: object save: failed");
tclpd_interp_error(result);
}
+ Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
}
diff --git a/tcl_extras.h b/tcl_extras.h
index 6d52989..9bca803 100644
--- a/tcl_extras.h
+++ b/tcl_extras.h
@@ -12,6 +12,8 @@
#define TCLPD_VERSION "0.2"
+#define InitArray(name, size, value) for(int zz=0; zz<(size); zz++) name[zz]=value
+
typedef struct _t_tcl {
t_object o;
Tcl_Obj* self;
diff --git a/tcl_widgetbehavior.cxx b/tcl_widgetbehavior.cxx
index 55634d5..8167803 100644
--- a/tcl_widgetbehavior.cxx
+++ b/tcl_widgetbehavior.cxx
@@ -2,10 +2,12 @@
#include <string.h>
int tclpd_guiclass_click(t_gobj* z, t_glist* glist, int xpix, int ypix, int shift, int alt, int dbl, int doit) {
- Tcl_Obj* av[9], *o = NULL;
+ Tcl_Obj* av[9]; InitArray(av, 9, NULL);
+ Tcl_Obj* o = NULL;
int i = 0;
t_tcl* x = (t_tcl*)z;
av[0] = x->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewStringObj("widgetbehavior", -1);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("click", -1);
@@ -24,7 +26,6 @@ int tclpd_guiclass_click(t_gobj* z, t_glist* glist, int xpix, int ypix, int shif
Tcl_IncrRefCount(av[8]);
int result = Tcl_EvalObjv(tcl_for_pd, 9, av, 0);
if(result != TCL_OK) {
- tclpd_interp_error(result);
goto error;
}
o = Tcl_GetObjResult(tcl_for_pd);
@@ -32,14 +33,17 @@ int tclpd_guiclass_click(t_gobj* z, t_glist* glist, int xpix, int ypix, int shif
if(strlen(Tcl_GetStringFromObj(o, NULL)) > 0) {
result = Tcl_GetIntFromObj(tcl_for_pd, o, &i);
if(result != TCL_OK) {
- tclpd_interp_error(result);
goto error;
}
}
goto cleanup;
+
error:
+ tclpd_interp_error(result);
+
cleanup:
if(o) Tcl_DecrRefCount(o);
+ Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
Tcl_DecrRefCount(av[3]);
@@ -52,10 +56,13 @@ cleanup:
}
void tclpd_guiclass_getrect(t_gobj* z, t_glist* owner, int* xp1, int* yp1, int* xp2, int* yp2) {
- Tcl_Obj* av[5], *o, *theList = NULL;
+ Tcl_Obj* av[5]; InitArray(av, 5, NULL);
+ Tcl_Obj* o;
+ Tcl_Obj* theList = NULL;
int tmp[4], i, length;
t_tcl* x = (t_tcl*)z;
av[0] = x->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewStringObj("widgetbehavior", -1);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("getrect", -1);
@@ -100,6 +107,7 @@ void tclpd_guiclass_getrect(t_gobj* z, t_glist* owner, int* xp1, int* yp1, int*
error:
cleanup:
if(theList) Tcl_DecrRefCount(theList);
+ Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
Tcl_DecrRefCount(av[3]);
@@ -107,10 +115,13 @@ cleanup:
}
void tclpd_guiclass_displace(t_gobj* z, t_glist* glist, int dx, int dy) {
- Tcl_Obj* av[5], *theList = NULL, *o;
+ Tcl_Obj* av[5]; InitArray(av, 5, NULL);
+ Tcl_Obj* theList = NULL;
+ Tcl_Obj* o;
int length, i, tmp[2];
t_tcl* x = (t_tcl*)z;
av[0] = x->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewStringObj("widgetbehavior", -1);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("displace", -1);
@@ -157,6 +168,7 @@ void tclpd_guiclass_displace(t_gobj* z, t_glist* glist, int dx, int dy) {
error:
cleanup:
if(theList) Tcl_DecrRefCount(theList);
+ Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
Tcl_DecrRefCount(av[3]);
@@ -164,9 +176,10 @@ cleanup:
}
void tclpd_guiclass_select(t_gobj* z, t_glist* glist, int selected) {
- Tcl_Obj* av[4];
+ Tcl_Obj* av[4]; InitArray(av, 4, NULL);
t_tcl* x = (t_tcl*)z;
av[0] = x->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewStringObj("widgetbehavior", -1);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("select", -1);
@@ -181,15 +194,17 @@ void tclpd_guiclass_select(t_gobj* z, t_glist* glist, int selected) {
goto cleanup;
error:
cleanup:
+ Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
Tcl_DecrRefCount(av[3]);
}
void tclpd_guiclass_activate(t_gobj* z, t_glist* glist, int state) {
- Tcl_Obj* av[4];
+ Tcl_Obj* av[4]; InitArray(av, 4, NULL);
t_tcl* x = (t_tcl*)z;
av[0] = x->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewStringObj("widgetbehavior", -1);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("activate", -1);
@@ -204,6 +219,7 @@ void tclpd_guiclass_activate(t_gobj* z, t_glist* glist, int state) {
goto cleanup;
error:
cleanup:
+ Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
Tcl_DecrRefCount(av[3]);
@@ -215,9 +231,10 @@ void tclpd_guiclass_delete(t_gobj* z, t_glist* glist) {
}
void tclpd_guiclass_vis(t_gobj* z, t_glist* glist, int vis) {
- Tcl_Obj* av[7];
+ Tcl_Obj* av[7]; InitArray(av, 7, NULL);
t_tcl* x = (t_tcl*)z;
av[0] = x->self;
+ Tcl_IncrRefCount(av[0]);
av[1] = Tcl_NewStringObj("widgetbehavior", -1);
Tcl_IncrRefCount(av[1]);
av[2] = Tcl_NewStringObj("vis", -1);
@@ -240,6 +257,7 @@ void tclpd_guiclass_vis(t_gobj* z, t_glist* glist, int vis) {
goto cleanup;
error:
cleanup:
+ Tcl_DecrRefCount(av[0]);
Tcl_DecrRefCount(av[1]);
Tcl_DecrRefCount(av[2]);
Tcl_DecrRefCount(av[3]);