Skip to content

Commit

Permalink
kernel: fix mem leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-mitchell committed Sep 12, 2023
1 parent c4fb7e2 commit 5eb42e8
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 25 deletions.
8 changes: 3 additions & 5 deletions etc/tst-local-vars.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
"""
TODO
This simple script adds the local variables used in a GAP tst file to the top
of the file.
"""
import os
import re
Expand All @@ -24,10 +25,7 @@ def main():
lvars.extend([x.group(1) for x in re.finditer(pattern1, lines)])
lvars.extend([x.group(1) for x in re.finditer(pattern2, lines)])
lvars = ", ".join(sorted([*{*lvars}]))
lvars = [
x if x[-1] != "," else x[:-1]
for x in textwrap.wrap(lvars, width=72)
]
lvars = [x if x[-1] != "," else x[:-1] for x in textwrap.wrap(lvars, width=72)]
lvars = [""] + ["#@local " + x for x in lvars]
lines = lines.split("\n")
pos = next(i for i in range(len(lines)) if "START_TEST" in lines[i])
Expand Down
49 changes: 49 additions & 0 deletions etc/tst-unbind-local-vars.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""
This simple script adds the "Unbind" statements to the end of a GAP tst file.
"""
import os
import re
import sys
import textwrap

import yaml
from bs4 import BeautifulSoup


def main():
if sys.version_info[0] < 3:
raise Exception("Python 3 is required")
args = sys.argv[1:]
pattern1 = re.compile(r"(\w+)\s*:=")
pattern2 = re.compile(r"for (\w+) in")
for fname in args:
lvars = []
with open(fname, "r") as f:
lines = f.read()
lvars.extend([x.group(1) for x in re.finditer(pattern1, lines)])
lvars.extend([x.group(1) for x in re.finditer(pattern2, lines)])
lvars = sorted([*{*lvars}])
lvars = [
"# Unbind local variables, auto-generated by etc/tst-unbind-local-vars.py"
] + [f"gap> Unbind({lvar});" for lvar in lvars]
lvars.append("")
lines = lines.split("\n")
pos1 = next(i for i in range(len(lines)) if "STOP_TEST" in lines[i]) - 1
try:
pos0 = next(
i
for i in range(len(lines))
if "etc/tst-unbind-local-vars.py" in lines[i]
)
except StopIteration:
pos0 = pos1
lines = lines[:pos0] + lvars + lines[pos1:]
lines = "\n".join(lines)
with open(fname, "w") as f:
print(f"Writing local variables to {fname}...")
f.write(lines)


if __name__ == "__main__":
main()
11 changes: 7 additions & 4 deletions gapbind14/include/gapbind14/gapbind14.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ namespace gapbind14 {
: SubtypeBase(nm, sbtyp) {}

void free(Obj o) override {
static_assert(IsGapBind14Type<T>::value,
"template parameter T must satisfy IsGapbind14Type<T>");
GAPBIND14_ASSERT(obj_subtype(o) == module().subtype<T>());
delete detail::obj_cpp_ptr<T>(o);
}
};
Expand Down Expand Up @@ -214,12 +217,12 @@ namespace gapbind14 {
_subtypes(),
_type_to_subtype() {}

Module(Module const&) = delete;
Module(Module&&) = delete;
Module(Module const&) = delete;
Module(Module&&) = delete;
Module& operator=(Module const&) = delete;
Module& operator=(Module&&) = delete;
Module& operator=(Module&&) = delete;

~Module() = default;
~Module();

void clear();

Expand Down
12 changes: 8 additions & 4 deletions gapbind14/include/gapbind14/to_cpp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ namespace gapbind14 {

std::string operator()(Obj o) const {
if (TNUM_OBJ(o) != T_STRING) {
ErrorQuit("expected string, found %s", (Int) TNAM_OBJ(o), 0L);
throw std::runtime_error(std::string("expected string, found ")
+ TNAM_OBJ(o));
}
return std::string(CSTR_STRING(o), GET_LEN_STRING(o));
}
Expand All @@ -106,7 +107,8 @@ namespace gapbind14 {

Int operator()(Obj o) const {
if (TNUM_OBJ(o) != T_INT) {
ErrorQuit("expected int, found %s", (Int) TNAM_OBJ(o), 0L);
throw std::runtime_error(std::string("expected int, found ")
+ TNAM_OBJ(o));
}
return INT_INTOBJ(o);
}
Expand All @@ -123,7 +125,8 @@ namespace gapbind14 {

bool operator()(Obj o) const {
if (TNUM_OBJ(o) != T_BOOL) {
ErrorQuit("expected bool, found %s", (Int) TNAM_OBJ(o), 0L);
throw std::runtime_error(std::string("expected bool, found ")
+ TNAM_OBJ(o));
}
return o == True ? true : false;
}
Expand All @@ -140,7 +143,8 @@ namespace gapbind14 {

std::vector<T> operator()(Obj o) const {
if (!IS_LIST(o)) {
ErrorQuit("expected list, found %s", (Int) TNAM_OBJ(o), 0L);
throw std::runtime_error(std::string("expected list, found ")
+ TNAM_OBJ(o));
}

size_t const N = LEN_LIST(o);
Expand Down
34 changes: 28 additions & 6 deletions gapbind14/src/gapbind14.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

#include "gapbind14/gapbind14.hpp"

#include <stdio.h> // for fprintf, stderr
#include <string.h> // for memcpy, strchr, strrchr
//
#include <stdio.h> // for fprintf, stderr
#include <string.h> // for memcpy, strchr, strrchr

#include <unordered_set> // for unordered_set, unordered_set<>::iterator

#include "gapbind14/gap_include.hpp" // for Obj etc
Expand Down Expand Up @@ -93,10 +93,32 @@ namespace gapbind14 {

// Module implementations

Module::~Module() {
clear();
for (auto *subtype : _subtypes) {
delete subtype;
}
}

void Module::clear() {
for (auto &func : _funcs) {
delete func.name;
if (func.nargs != 0) {
delete func.args;
}
delete func.cookie;
}
_funcs.clear();
for (auto &funcs : _mem_funcs) {
funcs.clear();

for (auto &vec : _mem_funcs) {
for (auto &func : vec) {
delete func.name;
if (func.nargs != 0) {
delete func.args;
}
delete func.cookie;
}
vec.clear();
}
}

Expand Down Expand Up @@ -266,7 +288,7 @@ namespace gapbind14 {
first_call = false;
InitGVarFuncsFromTable(GVarFuncs);
}
auto & m = module();
auto &m = module();
StructGVarFunc const *tab = m.funcs();

// init functions from m in the record named name
Expand Down
50 changes: 50 additions & 0 deletions tst/standard/attributes/homomorph.tst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
##
#############################################################################
##

## We don't use local variables in this test file because it doesn't play nice
## with something in this test file.

#
gap> START_TEST("Semigroups package: standard/attributes/homomorph.tst");
gap> LoadPackage("semigroups", false);;

Expand Down Expand Up @@ -1079,6 +1084,51 @@ gap> hom2 := SemigroupHomomorphismByImages(S, S, GeneratorsOfSemigroup(S),
gap> hom1 = hom2;
false
# Unbind local variables, auto-generated by etc/tst-unbind-local-vars.py
gap> Unbind(BruteForceHomoCheck);
gap> Unbind(BruteForceInverseCheck);
gap> Unbind(BruteForceIsoCheck);
gap> Unbind(F);
gap> Unbind(J);
gap> Unbind(K);
gap> Unbind(S);
gap> Unbind(T);
gap> Unbind(U);
gap> Unbind(V);
gap> Unbind(acting);
gap> Unbind(cong);
gap> Unbind(congs);
gap> Unbind(g);
gap> Unbind(gens);
gap> Unbind(gens1);
gap> Unbind(gens2);
gap> Unbind(gens3);
gap> Unbind(gensS);
gap> Unbind(gensT);
gap> Unbind(gensU);
gap> Unbind(gensV);
gap> Unbind(h);
gap> Unbind(hom);
gap> Unbind(hom1);
gap> Unbind(hom1bf);
gap> Unbind(hom1bfbi);
gap> Unbind(hom2);
gap> Unbind(hom3);
gap> Unbind(images);
gap> Unbind(images1);
gap> Unbind(images2);
gap> Unbind(images3);
gap> Unbind(imgs);
gap> Unbind(imgs2);
gap> Unbind(inv);
gap> Unbind(iso);
gap> Unbind(j);
gap> Unbind(map);
gap> Unbind(relations);
gap> Unbind(x);
gap> Unbind(y);
gap> Unbind(z);
#
gap> SEMIGROUPS.StopTest();
gap> STOP_TEST("Semigroups package: standard/attributes/homomorph.tst");
24 changes: 19 additions & 5 deletions tst/standard/semigroups/semifp.tst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
##
#############################################################################
##

## We don't use local variables in this test file because it doesn't play nice
## with AssignGeneratorVariables, which is used repeatedly here.

gap> START_TEST("Semigroups package: standard/semigroups/semifp.tst");
gap> LoadPackage("semigroups", false);;

Expand Down Expand Up @@ -2666,23 +2670,33 @@ true
gap> IsSubsemigroupOfFpMonoid(Range(map));
true
# SEMIGROUPS_UnbindVariables
gap> Unbind(a);
gap> Unbind(b);
# Unbind local variables, auto-generated by etc/tst-unbind-local-vars.py
gap> Unbind(BruteForceInverseCheck);
gap> Unbind(BruteForceIsoCheck);
gap> Unbind(f);
gap> Unbind(F);
gap> Unbind(G);
gap> Unbind(LoopIterator);
gap> Unbind(Noop);
gap> Unbind(R);
gap> Unbind(S);
gap> Unbind(T);
gap> Unbind(TestEnumerator);
gap> Unbind(TestIterator);
gap> Unbind(a);
gap> Unbind(b);
gap> Unbind(f);
gap> Unbind(factorizable);
gap> Unbind(inv);
gap> Unbind(iso);
gap> Unbind(len);
gap> Unbind(map);
gap> Unbind(rels);
gap> Unbind(s);
gap> Unbind(tst);
gap> Unbind(valid);
gap> Unbind(w);
gap> Unbind(x);
gap> Unbind(y);
#
gap> SEMIGROUPS.StopTest();
gap> STOP_TEST("Semigroups package: standard/semigroups/semifp.tst");
8 changes: 7 additions & 1 deletion tst/standard/tools/display.tst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
##
#############################################################################
##

## We don't use local variables in this test file because it doesn't play nice
## with something in this test file.

#
gap> START_TEST("Semigroups package: standard/tools/display.tst");
gap> LoadPackage("semigroups", false);;

Expand Down Expand Up @@ -1025,7 +1030,8 @@ gap> TikzRightCayleyDigraph(S);
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 2nd choice method found for `TikzString' on 1 arguments

# SEMIGROUPS_UnbindVariables
# Unbind local variables, auto-generated by etc/tst-unbind-local-vars.py
gap> Unbind(S);
gap> Unbind(x);
gap> Unbind(y);

Expand Down

0 comments on commit 5eb42e8

Please sign in to comment.