@@ -4165,10 +4165,18 @@ int cbm_store_fetch_call_edges(cbm_store_t *s, const char *project, int max_edge
41654165 bind_text (stmt , SKIP_ONE , project );
41664166 sqlite3_bind_int (stmt , 2 , max_edges > 0 ? max_edges + SKIP_ONE : CBM_NOT_FOUND );
41674167
4168+ /* Both arrays are STORE-class memory-core blocks: the caller releases them
4169+ * with cbm_store_free_call_edges, the only free that matches. */
41684170 int cap = ST_INIT_CAP_16 ;
41694171 int n = 0 ;
4170- int64_t * src = malloc ((size_t )cap * sizeof (int64_t ));
4171- int64_t * tgt = malloc ((size_t )cap * sizeof (int64_t ));
4172+ int64_t * src = cbm_alloc (CBM_MEM_CLASS_STORE , (size_t )cap * sizeof (int64_t ));
4173+ int64_t * tgt = cbm_alloc (CBM_MEM_CLASS_STORE , (size_t )cap * sizeof (int64_t ));
4174+ if (!src || !tgt ) {
4175+ sqlite3_finalize (stmt );
4176+ cbm_store_free_call_edges (src , tgt );
4177+ store_set_error (s , "fetch_call_edges: out of memory" );
4178+ return CBM_STORE_ERR ;
4179+ }
41724180 int scan_rc ;
41734181 while ((scan_rc = sqlite3_step (stmt )) == SQLITE_ROW ) {
41744182 if (max_edges > 0 && n >= max_edges ) {
@@ -4178,18 +4186,31 @@ int cbm_store_fetch_call_edges(cbm_store_t *s, const char *project, int max_edge
41784186 break ;
41794187 }
41804188 if (n >= cap ) {
4189+ size_t grown_bytes = (size_t )cap * ST_GROWTH * sizeof (int64_t );
4190+ int64_t * grown_src = cbm_realloc (CBM_MEM_CLASS_STORE , src , grown_bytes );
4191+ if (grown_src ) {
4192+ src = grown_src ;
4193+ }
4194+ int64_t * grown_tgt =
4195+ grown_src ? cbm_realloc (CBM_MEM_CLASS_STORE , tgt , grown_bytes ) : NULL ;
4196+ if (grown_tgt ) {
4197+ tgt = grown_tgt ;
4198+ }
4199+ if (!grown_src || !grown_tgt ) {
4200+ sqlite3_finalize (stmt );
4201+ cbm_store_free_call_edges (src , tgt );
4202+ store_set_error (s , "fetch_call_edges: out of memory" );
4203+ return CBM_STORE_ERR ;
4204+ }
41814205 cap *= ST_GROWTH ;
4182- src = safe_realloc (src , (size_t )cap * sizeof (int64_t ));
4183- tgt = safe_realloc (tgt , (size_t )cap * sizeof (int64_t ));
41844206 }
41854207 src [n ] = sqlite3_column_int64 (stmt , 0 );
41864208 tgt [n ] = sqlite3_column_int64 (stmt , 1 );
41874209 n ++ ;
41884210 }
41894211 sqlite3_finalize (stmt );
41904212 if (scan_rc != SQLITE_DONE && scan_rc != SQLITE_ROW ) {
4191- free (src );
4192- free (tgt );
4213+ cbm_store_free_call_edges (src , tgt );
41934214 store_set_error_sqlite (s , "fetch_call_edges scan" );
41944215 return CBM_STORE_ERR ;
41954216 }
@@ -4199,6 +4220,11 @@ int cbm_store_fetch_call_edges(cbm_store_t *s, const char *project, int max_edge
41994220 return CBM_STORE_OK ;
42004221}
42014222
4223+ void cbm_store_free_call_edges (int64_t * src , int64_t * tgt ) {
4224+ cbm_free (CBM_MEM_CLASS_STORE , src );
4225+ cbm_free (CBM_MEM_CLASS_STORE , tgt );
4226+ }
4227+
42024228int cbm_store_find_edges_by_source (cbm_store_t * s , int64_t source_id , cbm_edge_t * * out ,
42034229 int * count ) {
42044230 bind_id_t b = {source_id };
@@ -10647,6 +10673,10 @@ int cbm_louvain(const int64_t *nodes, int node_count, const cbm_louvain_edge_t *
1064710673 return cbm_leiden (nodes , node_count , edges , edge_count , 1.0 , out , out_count );
1064810674}
1064910675
10676+ void cbm_leiden_free (cbm_louvain_result_t * result ) {
10677+ cbm_free (CBM_MEM_CLASS_OTHER , result ); /* cbm_leiden allocates OTHER */
10678+ }
10679+
1065010680/* ── Architecture: community clusters via Leiden ───────────────── */
1065110681
1065210682enum {
0 commit comments