我的应用程序崩溃了,并在控制台上打印了以下内容:
sh [366]:/ bin / sh:第1行:367分段错误(核心已转储)。/myapp
我的问题是367在这里表示什么?
我在任何地方都找不到核心转储文件。
有什么线索可以在这种情况下调试分段错误吗?
答案 0 :(得分:5)
367是进程ID(程序段错误)的进程ID。您可以在function* watch() {
while (true) {
try {
yield call(delay,10000);
yield call(getAllFromServer);
} catch (error) {
yield put(actions.setErrorInStore(error));
}
}
}
function* watchPoll() {
while (true) {
yield take(actionType.WATCH_START);
yield race([
call(watch),
take(actionType.WATCH_PAUSE),
take(actionType.WATCH_STOP)
]);
}
}
export function* sagasNotificationWatcher() {
yield takeLatest(actionType.GET_NOTIFICATIONS, getAllFromServer);
yield takeLatest(actionType.GET_CURRENT_NOTIFICATION, setCurrent);
yield takeEvery(actionType.SET_HIDDEN, setHidden);
yield takeEvery(actionType.HIDE_SINGLE, hideSingleSelected);
yield takeEvery(actionType.SET_READ, setStatus);
yield takeEvery(actionType.SET_UNREAD, setStatus);
yield throttle(1500, actionType.SEARCH_NOTIFICATIONS, getAllFromServer);
yield takeLatest(actionType.SHOW_UNREAD, getAllFromServer);
yield takeEvery(actionType.SET_FILTERS, getAllFromServer);
yield takeEvery(actionType.SET_SEARCH_MODULE, getAllFromServer);
yield call(watchPoll) // if i pass in this call just watch, then this works, but if watchPoll it's stopping on yield call(delay,10000);
}
调试器下运行程序。
先阅读How To Debug Small Programs,然后阅读documentation of gdb
。考虑也使用valgrind。
任何线索在这种情况下如何调试分段错误?
如果该故障可以重现,则非常简单。在gdb
我在任何地方都找不到核心转储文件。
请仔细阅读core(5)(和getrlimit(2);也许核心转储已被某些gdb
bash内置函数禁用)。您的系统可能已配置(请参见proc(5))以其他方式转储内核(例如,通过systemd(1),可能在ulimit
下)。可能看到coredumpctl(1)和systemd-coredump(8)和coredump.conf(5)
在编译应用程序with /var/lib/systemd/coredump/
时,请不要忘记启用所有警告和调试信息(当然,可以改进代码以完全不发出警告)。
答案 1 :(得分:3)
通常,我调试分段错误的第一步是:
使用调试符号(-g
选项)编译应用程序,但保留优化选项以避免太多改动
在gdb
下运行gdb --args ./myprog
,然后在命令提示符下运行r
下的程序
如果幸运的话,程序崩溃了,请键入bt
(回溯)以查看它在哪个函数中崩溃,从哪个函数中调用,依次类推直至主程序(或线程启动)。
如果可能的话,一个更好的选择是在valgrind
下运行可执行文件,以查看它首先被发现的“不良”行为是什么。在许多情况下,做坏事情(例如在数组边界之外进行读取或写入操作)不会立即产生段错误,valgrid
会向您显示在您无权访问的位置上的首次读取或写入操作(可以在程序正常执行时静默地“工作”)。使用valgrind
的缺点是执行速度非常慢,因为该程序基本上是使用仿真处理器运行的;它是如此之慢,以至于可能无法在预期的上下文中运行该程序(例如,因为它需要与可能会超时的设备通信)。
另一个选择是使用地址清理器(-fsanitize=address
)编译程序。这将在可执行文件本身中添加代码,以检查边界之外的内存访问或释放的内存。优点是,尽管执行速度仍然比常规的非插入式可执行文件慢,但比在valgrind
下运行程序要快得多。
答案 2 :(得分:1)
如果核心转储不可用,GDB甚至可以使用.exe文件进行调试。
target exec -- Use an executable file as a target
以这种方式使用它:
(gdb) target exec a.exe