使用已弃用Google Assistant Python库时释放内存触发段错误求助
解决已弃用Google Assistant Python库中
assistant_free触发的段错误 我目前在使用已弃用的Google Assistant Python库,因为只有它支持“Hey Google”这类热词唤醒功能,暂时没有替代方案所以不得不继续用。现在遇到一个问题:调用self._lib.assistant_free(self._inst)时会触发Segmentation Fault(段错误),明明self._inst已经在构造函数里初始化过,而且全程都在正常使用。添加自定义语音命令或者退出程序的时候都会触发这个错误,相关信息如下:
栈追踪
Thread 0xb6f8fb40 (most recent call first): File "/home/steven/env/lib/python3.7/site-packages/google/assistant/library/assistant.py", line 119 in __exit__ File "/home/steven/GassistPi/src/main.py", line 1105 in main File "/home/steven/GassistPi/src/main.py", line 1110 in <module> Segmentation fault
相关代码
构造函数
def __init__(self, credentials, device_model_id): warnings.warn('Google Assistant Library for Python is deprecated', DeprecationWarning) if not device_model_id: raise ValueError("device_model_id must be a non-empty string") self._event_queue = IterableEventQueue() self._load_lib() self._credentials_refresher = None self._shutdown = False self._event_callback = EVENT_CALLBACK(self) self._inst = c_void_p( self._lib.assistant_new( self._event_callback, device_model_id.encode('ASCII'), None)) print(self._inst) self._credentials_refresher = CredentialsRefresher( credentials, self._set_credentials) self._credentials_refresher.start()
__exit__方法
def __exit__(self, exception_type, exception_value, traceback): """Frees allocated memory belonging to the Assistant.""" if self._credentials_refresher: self._credentials_refresher.stop() self._credentials_refresher = None self._shutdown = True self._lib.assistant_free(self._inst)
可能的原因与解决办法
1. 重复释放或野指针问题
段错误大概率是因为assistant_free被调用多次,或者self._inst已变成野指针。可以增加判断逻辑,确保只释放一次,且释放后置空指针:
def __exit__(self, exception_type, exception_value, traceback): """Frees allocated memory belonging to the Assistant.""" if self._credentials_refresher: self._credentials_refresher.stop() self._credentials_refresher = None self._shutdown = True # 增加判断避免重复释放,释放后置空指针 if self._inst and self._inst.value is not None: self._lib.assistant_free(self._inst) self._inst = None
2. 线程资源竞争问题
CredentialsRefresher是独立线程,可能存在资源竞争。停止刷新器后需等待线程完全退出,再释放实例:
def __exit__(self, exception_type, exception_value, traceback): """Frees allocated memory belonging to the Assistant.""" if self._credentials_refresher: self._credentials_refresher.stop() # 等待刷新器线程完全退出 self._credentials_refresher.join() self._credentials_refresher = None self._shutdown = True if self._inst and self._inst.value is not None: self._lib.assistant_free(self._inst) self._inst = None
3. 回调事件未处理完成
绑定的回调事件可能还有未处理的队列任务,导致释放实例时触发错误。先清空事件队列再执行释放:
def __exit__(self, exception_type, exception_value, traceback): """Frees allocated memory belonging to the Assistant.""" self._shutdown = True # 清空事件队列,确保无 pending 回调 while not self._event_queue.empty(): try: self._event_queue.get_nowait() except queue.Empty: pass if self._credentials_refresher: self._credentials_refresher.stop() self._credentials_refresher.join() self._credentials_refresher = None if self._inst and self._inst.value is not None: self._lib.assistant_free(self._inst) self._inst = None
内容的提问来源于stack exchange,提问作者Ageis
相关产品推荐
相关产品推荐

