Возвращаемое значение C / Cython частично зависит от фрейма / функции, в которую возвращается значение - PullRequest
0 голосов
/ 20 марта 2020

Я уже несколько дней пытаюсь отлаживать эту программу на C / Cython, и я очень близко к ней подхожу. Библиотека priorityqueue , которую я использую, обеспечивает pqueue_insert и pqueue_pop. Мой псевдокод Cython выглядит следующим образом:

pick_pop_location = ? // set to 1 or 2
cdef void main():
    node_t current_element, pqueue_t* pq = initialize() // exact implementation doesn't matter
    push_wrapper(pq, &current_element)
    if pick_pop_location == 1:
        popped_after_returning_to_main = (<node_t*>pqueue_pop(pq))[0]
        print(popped_after_returning_to_main)

cdef void push_wrapper(pqueue_t* pq, node_t* current_element):
    node_t new_element = build_new_element(current_element) // exact implementation doesn't matter
    pqueue_insert(pq, &new_element)
    if pick_pop_location == 2:
        popped_immediately = (<node_t*>pqueue_pop(pq))[0]
        print(popped_immediately_inside_push_wrapper)

, а node_t выглядит следующим образом:

ctypedef struct node_t:
    pqueue_pri_t m
    int row
    int col

(Обратите внимание, что вместо этого я изменил pqueue_pri_t на double unsigned long long в libpqueue pqueue.h, хотя это не должно иметь значения, но я просто делаю здесь должную осмотрительность).

Теперь перейдем к интересной части. Если Я установил pick_pop_location = 2, он будет печатать

// popped_immediately_inside_push_wrapper

{'m': -1456.645295, 'row': 244, 'col': 1}

... что правильно . Но если я установлю pick_pop_location = 1, будет напечатано

// popped_after_returning_to_main

{'m': -1456.645295, 'row': -1739027664, 'col': 32764}

... что частично неверно : значение 'm' сохранено, но значения 'row' и 'col' имеют случайно изменено ( они меняются при каждом запуске программы).

Как это может произойти? Что (очевидно) идет не так после выхода из push_wrapper фрейма?

и

Как я могу отладить это? У меня нет опыта изменения значений между кадрами.

1 Ответ

1 голос
/ 20 марта 2020

Здесь приведено несколько догадок, учитывая неполный пример:

node_t new_element = build_new_element(current_element)

new_element выделено в стеке - оно существует, только когда работает push_wrapper.

pqueue_insert(pq, &new_element)

Я предполагаю, что здесь хранится указатель, а не новая копия элемента. После push_wrapper возвращает указатель указывает на бессмысленность.


С точки зрения того, как вы отлаживаете это: это поведение довольно типично для висячих указателей: либо вы пытаетесь прочитать из указателя, который больше не является допустимый (как я думаю, что здесь происходит) или вы написали указатель, который больше не действителен. Перемещенные в стеке переменные являются очевидным источником недействительных указателей.

...