Ver Fonte

fix memory leak of `chunked_array2d`

blueloveTH há 10 meses atrás
pai
commit
c7dbb8bd7f
5 ficheiros alterados com 26 adições e 9 exclusões
  1. 2 1
      build.sh
  2. 3 1
      build_g.sh
  3. 1 1
      include/pocketpy/objects/base.h
  4. 15 4
      src/modules/array2d.c
  5. 5 2
      src/public/internal.c

+ 2 - 1
build.sh

@@ -16,10 +16,11 @@ if [ $? -ne 0 ]; then
 fi
 
 SRC=$(find src/ -name "*.c")
+SRC2=${1:-src2/main.c}
 
 echo "> Compiling and linking source files... "
 
-clang -std=c11 -O2 -Wfatal-errors -Iinclude -DNDEBUG -o main src2/main.c $SRC -lm -ldl
+clang -std=c11 -O2 -Wfatal-errors -Iinclude -DNDEBUG -o main $SRC $SRC2 -lm -ldl
 
 if [ $? -eq 0 ]; then
     echo "Build completed. Type \"./main\" to enter REPL."

+ 3 - 1
build_g.sh

@@ -12,6 +12,8 @@ if [ "$(uname)" == "Darwin" ]; then
     SANITIZE_FLAGS="-fsanitize=address,undefined"
 fi
 
+SRC2=${1:-src2/main.c}
+
 echo "Compiling C files..."
-clang $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main
+clang $FLAGS $SANITIZE_FLAGS $SRC $SRC2 -o main
 

+ 1 - 1
include/pocketpy/objects/base.h

@@ -4,7 +4,7 @@
 
 typedef struct PyObject PyObject;
 typedef struct VM VM;
-extern VM* pk_current_vm;
+extern _Thread_local VM* pk_current_vm;
 
 typedef struct py_TValue {
     py_Type type;

+ 15 - 4
src/modules/array2d.c

@@ -909,7 +909,10 @@ static py_TValue* c11_chunked_array2d__new_chunk(c11_chunked_array2d* self, c11_
     if(!py_isnone(&self->context_builder)) {
         py_newvec2i(&data[0], pos);
         bool ok = py_call(&self->context_builder, 1, &data[0]);
-        if(!ok) return NULL;
+        if(!ok) {
+            PK_FREE(data);
+            return NULL;
+        }
         data[0] = *py_retval();
     } else {
         data[0] = *py_None();
@@ -1103,6 +1106,7 @@ static bool chunked_array2d__len__(int argc, py_Ref argv) {
 static bool chunked_array2d_clear(int argc, py_Ref argv) {
     PY_CHECK_ARGC(1);
     c11_chunked_array2d* self = py_touserdata(argv);
+    c11__foreach(c11_chunked_array2d_chunks_KV, &self->chunks, p_kv) PK_FREE(p_kv->value);
     c11_chunked_array2d_chunks__clear(&self->chunks);
     self->last_visited.value = NULL;
     py_newnone(py_retval());
@@ -1166,9 +1170,16 @@ static bool chunked_array2d_remove_chunk(int argc, py_Ref argv) {
     PY_CHECK_ARG_TYPE(1, tp_vec2i);
     c11_chunked_array2d* self = py_touserdata(argv);
     c11_vec2i pos = py_tovec2i(&argv[1]);
-    bool ok = c11_chunked_array2d_chunks__del(&self->chunks, pos);
-    self->last_visited.value = NULL;
-    py_newbool(py_retval(), ok);
+    py_TValue* data = c11_chunked_array2d_chunks__get(&self->chunks, pos, NULL);
+    if(data != NULL) {
+        PK_FREE(data);
+        bool ok = c11_chunked_array2d_chunks__del(&self->chunks, pos);
+        assert(ok);
+        self->last_visited.value = NULL;
+        py_newbool(py_retval(), ok);
+    } else {
+        py_newbool(py_retval(), false);
+    }
     return true;
 }
 

+ 5 - 2
src/public/internal.c

@@ -5,14 +5,15 @@
 #include "pocketpy/common/utils.h"
 #include "pocketpy/interpreter/vm.h"
 
-VM* pk_current_vm;
+_Thread_local VM* pk_current_vm;
 
+static bool pk_initialized;
 static VM pk_default_vm;
 static VM* pk_all_vm[16];
 static py_TValue _True, _False, _None, _NIL;
 
 void py_initialize() {
-    if(pk_current_vm) {
+    if(pk_initialized) {
         // c11__abort("py_initialize() can only be called once!");
         return;
     }
@@ -35,6 +36,8 @@ void py_initialize() {
     py_newnone(&_None);
     py_newnil(&_NIL);
     VM__ctor(&pk_default_vm);
+
+    pk_initialized = true;
 }
 
 py_GlobalRef py_True() { return &_True; }