Skip to content

Commit c5307c7

Browse files
Prerak SinghPrerak Singh
authored andcommitted
segfault fix
1 parent 95795cc commit c5307c7

File tree

4 files changed

+65
-9
lines changed

4 files changed

+65
-9
lines changed

pydatastructs/graphs/_backend/cpp/Algorithms.hpp

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,26 @@ static PyObject* minimum_spanning_tree_prim_adjacency_list(PyObject* self, PyObj
204204
for (const auto& [adj_name, _] : start_node->adjacent) {
205205
std::string key = make_edge_key(start, adj_name);
206206
GraphEdge* edge = graph->edges[key];
207-
pq.push({start, adj_name, edge->value, edge->value_type});
207+
EdgeTuple et;
208+
et.source = start;
209+
et.target = adj_name;
210+
et.value_type = edge->value_type;
211+
212+
switch (edge->value_type) {
213+
case DataType::Int:
214+
et.value = std::get<int64_t>(edge->value);
215+
break;
216+
case DataType::Double:
217+
et.value = std::get<double>(edge->value);
218+
break;
219+
case DataType::String:
220+
et.value = std::get<std::string>(edge->value);
221+
break;
222+
default:
223+
et.value = std::monostate{};
224+
}
225+
226+
pq.push(et);
208227
}
209228

210229
while (!pq.empty()) {
@@ -233,20 +252,24 @@ static PyObject* minimum_spanning_tree_prim_adjacency_list(PyObject* self, PyObj
233252

234253
std::string key_uv = make_edge_key(edge.source, edge.target);
235254
GraphEdge* new_edge = PyObject_New(GraphEdge, &GraphEdgeType);
255+
PyObject_Init(reinterpret_cast<PyObject*>(new_edge), &GraphEdgeType);
256+
new (&new_edge->value) std::variant<std::monostate, int64_t, double, std::string>(edge.value);
257+
new_edge->value_type = edge.value_type;
236258
Py_INCREF(u);
237259
Py_INCREF(v);
238260
new_edge->source = reinterpret_cast<PyObject*>(u);
239261
new_edge->target = reinterpret_cast<PyObject*>(v);
240-
new (&new_edge->value) std::variant<std::monostate, int64_t, double, std::string>(edge.value);
241-
new_edge->value_type = edge.value_type;
242262
mst->edges[key_uv] = new_edge;
243263

244264
std::string key_vu = make_edge_key(edge.target, edge.source);
245265
GraphEdge* new_edge_rev = PyObject_New(GraphEdge, &GraphEdgeType);
246-
new_edge_rev->source = reinterpret_cast<PyObject*>(v);
247-
new_edge_rev->target = reinterpret_cast<PyObject*>(u);
266+
PyObject_Init(reinterpret_cast<PyObject*>(new_edge_rev), &GraphEdgeType);
248267
new (&new_edge_rev->value) std::variant<std::monostate, int64_t, double, std::string>(edge.value);
249268
new_edge_rev->value_type = edge.value_type;
269+
Py_INCREF(u);
270+
Py_INCREF(v);
271+
new_edge_rev->source = reinterpret_cast<PyObject *>(v);
272+
new_edge_rev->target = reinterpret_cast<PyObject*>(u);
250273
mst->edges[key_vu] = new_edge_rev;
251274

252275
AdjacencyListGraphNode* next_node = graph->node_map[edge.target];
@@ -255,10 +278,27 @@ static PyObject* minimum_spanning_tree_prim_adjacency_list(PyObject* self, PyObj
255278
if (visited.count(adj_name)) continue;
256279
std::string key = make_edge_key(edge.target, adj_name);
257280
GraphEdge* adj_edge = graph->edges[key];
258-
pq.push({edge.target, adj_name, adj_edge->value, adj_edge->value_type});
281+
EdgeTuple adj_et;
282+
adj_et.source = edge.target;
283+
adj_et.target = adj_name;
284+
adj_et.value_type = adj_edge->value_type;
285+
286+
switch (adj_edge->value_type) {
287+
case DataType::Int:
288+
adj_et.value = std::get<int64_t>(adj_edge->value);
289+
break;
290+
case DataType::Double:
291+
adj_et.value = std::get<double>(adj_edge->value);
292+
break;
293+
case DataType::String:
294+
adj_et.value = std::get<std::string>(adj_edge->value);
295+
break;
296+
default:
297+
adj_et.value = std::monostate{};
298+
}
299+
300+
pq.push(adj_et);
259301
}
260302
}
261-
262-
Py_INCREF(mst);
263303
return reinterpret_cast<PyObject*>(mst);
264304
}

pydatastructs/graphs/tests/test_algorithms.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,19 @@ def _test_minimum_spanning_tree_cpp(ds, algorithm, *args):
211211
assert str(mst.get_edge('d','c')) in expected_mst
212212
assert str(mst.get_edge('b','d')) in expected_mst
213213
assert mst.num_edges() == 8
214+
a=AdjacencyListGraphNode('0', 0, backend = Backend.CPP)
215+
b=AdjacencyListGraphNode('1', 0, backend = Backend.CPP)
216+
c=AdjacencyListGraphNode('2', 0, backend = Backend.CPP)
217+
d=AdjacencyListGraphNode('3', 0, backend = Backend.CPP)
218+
g2 = Graph(a,b,c,d,backend = Backend.CPP)
219+
g2.add_edge('0', '1', 74)
220+
g2.add_edge('1', '0', 74)
221+
g2.add_edge('0', '3', 55)
222+
g2.add_edge('3', '0', 55)
223+
g2.add_edge('1', '2', 74)
224+
g2.add_edge('2', '1', 74)
225+
mst2=minimum_spanning_tree(g2, "prim", backend = Backend.CPP)
226+
assert mst2.num_edges()==6
214227

215228
fmst = minimum_spanning_tree
216229
fmstp = minimum_spanning_tree_parallel

pydatastructs/utils/_backend/cpp/GraphEdge.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef struct {
1919
} GraphEdge;
2020

2121
static void GraphEdge_dealloc(GraphEdge* self) {
22+
self->value.~decltype(self->value)();
2223
Py_XDECREF(self->source);
2324
Py_XDECREF(self->target);
2425
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
@@ -160,7 +161,7 @@ inline PyTypeObject GraphEdgeType = {
160161
/* tp_iternext */ 0,
161162
/* tp_methods */ 0,
162163
/* tp_members */ 0,
163-
/* tp_getset */ 0,
164+
/* tp_getset */ GraphEdge_getsetters,
164165
/* tp_base */ 0,
165166
/* tp_dict */ 0,
166167
/* tp_descr_get */ 0,

pydatastructs/utils/_backend/cpp/GraphNode.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ typedef struct {
2121
} GraphNode;
2222

2323
static void GraphNode_dealloc(GraphNode* self){
24+
self->name.~basic_string();
25+
self->data.~decltype(self->data)();
2426
Py_TYPE(self)->tp_free(reinterpret_cast<PyTypeObject*>(self));
2527
}
2628

0 commit comments

Comments
 (0)