59 cc

本文详述了Loki,一个由Grafana Labs开发的轻量化日志聚合系统,作为ELK替代品,其特点是不全文索引,只索引标签,节省资源。Loki与Prometheus兼容,特别适合Kubernetes环境。文章介绍了如何在Grafana中配置和使用Loki,以及其部署、标签匹配模式和日志管理的最佳实践。

cc

(gdb) bt #0 lv_obj_get_ext_draw_size (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_draw.c:313 #1 0x0004f430 in lv_obj_invalidate (obj=obj@entry=0x0) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_pos.c:847 #2 0x00032ec0 in lv_image_set_src (obj=0x0, src=0x25071f) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/widgets/image/lv_image.c:206 #3 0x000acdc2 in main_menu_event_cb (e=<optimized out>) at TpMenu.c:464 #4 0x0003c40e in lv_event_send (list=list@entry=0x3baf44 <work_mem_int+1306920>, e=e@entry=0xbe88b2a4, preprocess=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_event.c:77 #5 0x000481f8 in event_send_core (e=e@entry=0xbe88b2a4) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_event.c:367 #6 0x000482de in lv_obj_send_event (obj=<optimized out>, event_code=<optimized out>, param=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/core/lv_obj_event.c:67 #7 0x00017bf0 in send_event (code=LV_EVENT_CLICKED, param=0x37d478 <work_mem_int+1054300>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:2038 #8 0x0001842c in indev_proc_release (indev=indev@entry=0x37d478 <work_mem_int+1054300>, is_right=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:1634 #9 0x000186a0 in indev_pointer_proc (data=0xbe88b34c, i=0x37d478 <work_mem_int+1054300>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:777 #10 lv_indev_read (indev=<optimized out>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:273 #11 lv_indev_read (indev=0x37d478 <work_mem_int+1054300>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/indev/lv_indev.c:219 #12 0x0003fa7c in lv_timer_exec (timer=0x37d564 <work_mem_int+1054536>) at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:326 #13 lv_timer_handler () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:107 #14 lv_timer_handler () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/lvgl/src/misc/lv_timer.c:63 #15 0x000156fe in main () at /home/xiejikai/24q3/torchlight/build_dir/target-arm-openwrt-linux-uclibcgnueabihf/nvrgui_lvgl/main.c:68 (gdb) f 3 #3 0x000acdc2 in main_menu_event_cb (e=<optimized out>) at TpMenu.c:464 464 lv_image_set_src(lv_obj_get_child(lv_obj_get_child(main_container, data->main_id * 2), TP_MENU_MAIN_IMAGE_RECT), data->main_img_src_checked); (gdb) p data->main_id * 2 $1 = 10 (gdb) p main_container $2 = (lv_obj_t *) 0x3c59cc <work_mem_int+1350576> (gdb) p main_container->spec_attr $3 = (lv_obj_spec_attr_t *) 0x3d6750 <work_mem_int+1419572> (gdb) p *(lv_obj_spec_attr_t *)0x3d6750 $4 = {children = 0x3e1d94 <work_mem_int+1466232>, group_p = 0x0, event_list = {data = 0x0, size = 0, capacity = 0, element_size = 0}, scroll = {x = 0, y = 0}, ext_click_pad = 0, ext_draw_size = 0, child_cnt = 11, scrollbar_mode = 3, scroll_snap_x = 0, scroll_snap_y = 0, scroll_dir = 15, layer_type = 0} (gdb) p main_container->spec_attr->children $5 = (lv_obj_t **) 0x3e1d94 <work_mem_int+1466232> (gdb) p main_container->spec_attr->children[9] $6 = (lv_obj_t *) 0x3e6b20 <work_mem_int+1486084> (gdb) p main_container->spec_attr->children[10] $7 = (lv_obj_t *) 0x3ce268 <work_mem_int+1385548> (gdb) p main_container->spec_attr->child_cnt $8 = 11 (gdb) p main_container->spec_attr->children[10]->spec_attr $9 = (lv_obj_spec_attr_t *) 0x0 (gdb) p main_container->spec_attr->children[9]->spec_attr $10 = (lv_obj_spec_attr_t *) 0x3baf3c <work_mem_int+1306912> (gdb) p main_container->spec_attr->children[11]->spec_attr $11 = (lv_obj_spec_attr_t *) 0x0 (gdb) p main_container->spec_attr->children[11] $12 = (lv_obj_t *) 0x3ce268 <work_mem_int+1385548> (gdb) p *(lv_obj_spec_attr_t *)0x3baf3c $13 = {children = 0x3e1d08 <work_mem_int+1466092>, group_p = 0x0, event_list = {data = 0x3e5438 <work_mem_int+1480220> "\330S>", size = 3, capacity = 5, element_size = 4}, scroll = {x = 0, y = 0}, ext_click_pad = 0, ext_draw_size = 0, child_cnt = 2, scrollbar_mode = 3, scroll_snap_x = 0, scroll_snap_y = 0, scroll_dir = 15, layer_type = 0} (gdb) p main_container->spec_attr->children[10]->spec_attr $14 = (lv_obj_spec_attr_t *) 0x0 (gdb) p *(lv_obj_t *) 0x3ce268 $15 = {class_p = 0x21e170 <lv_obj_class>, parent = 0x3c59cc <work_mem_int+1350576>, spec_attr = 0x0, styles = 0x3ce2a4 <work_mem_int+1385608>, style_main_prop_is_set = 2639, style_other_prop_is_set = 4111, user_data = 0x0, id = 0x1de05 <ensureBits32+44>, coords = {x1 = 26, y1 = 90, x2 = 276, y2 = 91}, flags = 47975, state = 0, layout_inv = 0, readjust_scroll_after_layout = 0, scr_layout_inv = 0, skip_trans = 0, style_cnt = 4, h_layout = 0, w_layout = 0, is_deleting = 0} (gdb) p *(lv_obj_t *) 0x3e6b20 $16 = {class_p = 0x21e170 <lv_obj_class>, parent = 0x3c59cc <work_mem_int+1350576>, spec_attr = 0x3baf3c <work_mem_int+1306912>, styles = 0x3e5450 <work_mem_int+1480244>, style_main_prop_is_set = 2639, style_other_prop_is_set = 4111, user_data = 0x0, id = 0x1de04 <ensureBits32+44>, coords = {x1 = 26, y1 = 533, x2 = 276, y2 = 572}, flags = 47974, state = 18, layout_inv = 0, readjust_scroll_after_layout = 0, scr_layout_inv = 0, skip_trans = 0, style_cnt = 5, h_layout = 0, w_layout = 0, is_deleting = 0} 帮我分析如下调用栈
最新发布
11-12
<think>我们有一个GDB的调用栈(backtrace)和一系列的调试命令输出。用户要求分析这个调用栈。 调用栈显示程序崩溃在`lv_obj_get_ext_draw_size`函数,并且传入的`obj`参数为0(空指针)。 通过回溯,我们看到: #0 lv_obj_get_ext_draw_size(obj=0x0) // 这里传入空指针 #1 lv_obj_invalidate(obj=0x0) // 也是空指针 #2 lv_image_set_src(obj=0x0, ...) // 设置图片源时,对象为空指针 #3 在main_menu_event_cb函数中,调用了lv_image_set_src 用户还提供了在frame 3(main_menu_event_cb)中的一些调试信息: 在TpMenu.c的第464行,调用了: lv_image_set_src(lv_obj_get_child(lv_obj_get_child(main_container, data->main_id * 2), TP_MENU_MAIN_IMAGE_RECT), data->main_img_src_checked); 其中,data->main_id * 2 的值是10。 然后,用户打印了main_container(一个lv_obj_t指针)以及它的spec_attr成员(一个lv_obj_spec_attr_t结构体指针)的内容。 main_container->spec_attr->child_cnt = 11,说明有11个子对象。 接着,用户尝试访问子对象数组(children)的第9、10、11个元素(索引从0开始): children[9] 的地址是0x3e6b20,它的spec_attr不为空。 children[10] 的地址是0x3ce268,它的spec_attr为空(0x0)。 children[11] 的地址是0x3ce268(与children[10]相同?这里可能是用户输入错误,因为数组索引11应该在第10个之后,而child_cnt=11,所以最大索引为10,索引11越界了?) 但是,请注意:用户打印了children[11](索引为11)的地址,这已经超出了child_cnt=11的范围(索引0到10)。然而,在C语言中,数组索引从0开始,所以有效的索引是0到10。索引11是第12个元素,已经越界。 然而,在调用栈中,崩溃的原因是传入了一个空指针。具体在TpMenu.c的464行,我们调用了: lv_obj_get_child(main_container, data->main_id * 2) // 这里data->main_id*2=10 然后对返回的对象再调用lv_obj_get_child(..., TP_MENU_MAIN_IMAGE_RECT)(假设TP_MENU_MAIN_IMAGE_RECT是一个索引) 分析: lv_obj_get_child(main_container, 10) 返回的是第10个孩子(即索引为10,因为是数组索引,所以是第11个孩子?注意:lvgl中的lv_obj_get_child函数返回的是第index个孩子,index从0开始,所以index=10就是第11个孩子,而main_container有11个孩子(索引0到10),所以这是合法的。 但是,当我们访问这个孩子(位于0x3ce268)时,发现它的spec_attr成员为NULL。这可能是导致后续问题的原因。 然后,我们尝试对这个对象(0x3ce268)调用lv_obj_get_child(..., TP_MENU_MAIN_IMAGE_RECT)(假设TP_MENU_MAIN_IMAGE_RECT是一个索引,比如0或1等)。但是,这个对象(0x3ce268)的spec_attr为NULL,这意味着它没有特殊属性,可能不是一个容器(container)对象,或者它没有被正确初始化。 在lvgl中,每个对象都有一个基本的结构,spec_attr用于存储一些额外的属性(例如子对象列表)。如果这个对象本应该有子对象,那么spec_attr就不应该为NULL。如果为NULL,那么访问其子对象就会有问题。 因此,崩溃的原因是:在main_menu_event_cb函数中,我们试图从一个对象(通过lv_obj_get_child(main_container,10)获得)中再获取一个子对象,但这个对象(0x3ce268)并没有初始化其spec_attr(即没有子对象),所以当我们试图获取它的第TP_MENU_MAIN_IMAGE_RECT个孩子时,内部可能会调用类似访问spec_attr->children数组的操作,而由于spec_attr为NULL,就会导致空指针解引用。 具体到崩溃点: 崩溃在lv_obj_get_ext_draw_size,参数obj=0x0,说明在某个环节得到了一个空指针。 回溯发现,这个空指针来自lv_image_set_src,而该函数的第一个参数(即图像对象)为空指针。 在main_menu_event_cb中,我们传给lv_image_set_src的对象是通过两次lv_obj_get_child得到的。所以,很可能是第二次lv_obj_get_child返回了空指针。 为什么第二次lv_obj_get_child会返回空指针? 因为第一次lv_obj_get_child(main_container,10)返回的对象(0x3ce268)是一个没有spec_attr的对象(也就是说它没有子对象),那么当我们试图获取它的第TP_MENU_MAIN_IMAGE_RECT个子对象时,lv_obj_get_child函数内部会尝试访问spec_attr->children,由于spec_attr为NULL,就会导致空指针访问。但是,在lv_obj_get_child函数中,如果对象没有子对象(即spec_attr为NULL或者child_cnt为0),那么它应该返回NULL。因此,这里第二次调用lv_obj_get_child返回了NULL,然后我们把这个NULL传给了lv_image_set_src,进而导致了崩溃。 所以,问题出在:我们试图从一个没有子对象的对象中获取子对象。为什么这个对象(0x3ce268)没有子对象?可能是创建这个对象时没有正确初始化,或者它本不应该有子对象(例如,它只是一个图像对象,而不是容器)。 解决方案: 1. 检查TpMenu.c中创建main_container的第10个子对象(索引10)的代码,确认它是否应该是一个容器(即可以包含子对象)。如果不是,那么就不应该从中获取子对象。 2. 检查在创建这个对象时,是否正确地初始化了它的spec_attr(如果需要包含子对象,则应该调用相应的函数来初始化)。 3. 或者,在获取子对象之前,先检查返回的对象是否有效,以及它是否有子对象。 另外,用户打印了main_container->spec_attr->children[11](索引11),这已经越界了(child_cnt=11,索引范围0到10)。越界访问可能导致未定义行为,可能会破坏内存,这也可能是导致spec_attr为NULL的原因之一(内存被破坏)。所以,需要检查代码中是否有越界访问数组的情况。 综上所述,崩溃的直接原因是尝试从一个非容器对象(其spec_attr为NULL)中获取子对象,导致后续传入了空指针。根本原因可能是对象创建不正确或越界访问导致内存破坏。 因此,建议: - 检查main_container的第10个子对象(索引10)的创建过程。 - 确保在访问数组(如children数组)时不越界(例如,不要访问索引11)。 - 在调用lv_obj_get_child后,检查返回的指针是否有效,以及是否具有子对象(如果要继续获取子对象)。 注意:在GDB输出中,用户打印了children[10](索引10)的地址是0x3ce268,而children[11](索引11)的地址也是0x3ce268?这很奇怪,因为连续的数组元素地址应该不同,除非数组元素类型是空结构或者只有一个元素?但这里是指针数组,每个元素是一个指针,所以地址应该递增。这里可能是用户打印错误,或者在内存中这个数组的后面正好是这个值(越界访问到了无效内存)。 但是,从main_container->spec_attr->children数组的打印来看,索引9和10都是有效的指针,而索引11则与索引10相同(这可能是因为数组后面就是0x3ce268这个值?),但无论如何,访问索引11是越界的,是不安全的。 所以,重点检查:在代码中是否无意中访问了children数组的越界索引(例如,循环条件是否写错?)。 </think>### 分析结论 根据提供的GDB调用栈和调试信息,程序崩溃的根本原因是**空指针解引用**,具体分析如下: 1. **崩溃源头**(#0帧): ```c lv_obj_get_ext_draw_size(obj=0x0) // 参数obj为空指针 ``` - 当尝试访问空指针对象(`0x0`)的内部属性时触发段错误。 2. **调用链溯源**: - `main_menu_event_cb`(#3帧)尝试设置图像源: ```c lv_image_set_src(..., data->main_img_src_checked); // TpMenu.c:464 ``` - 其中第一个参数是通过嵌套调用获得的指针: ```c lv_obj_get_child(lv_obj_get_child(main_container, 10), ...) ``` 3. **关键问题**: - `lv_obj_get_child(main_container, 10)` 返回对象地址 `0x3ce268` - 但该对象的 `spec_attr` 成员为 **`NULL`**(见GDB输出): ```gdb (gdb) p main_container->spec_attr->children[10]->spec_attr $14 = (lv_obj_spec_attr_t *) 0x0 // 关键空指针! ``` - 后继操作(如 `lv_obj_get_child()` 或样式计算)需访问 `spec_attr` 导致崩溃。 4. **对象状态对比**: | 对象地址 | `spec_attr` 状态 | 有效性 | |---------------|------------------|--------| | `0x3e6b20`(索引9) | 有效指针 (`0x3baf3c`) | ✔️ 正常 | | `0x3ce268`(索引10)| `NULL` | ❌ 异常 | 5. **根本原因**: - 索引10的子对象(`0x3ce268`)未正确初始化,其核心属性结构体 `spec_attr` 未被创建。 - 可能原因: - 对象创建时遗漏初始化代码 - 内存分配失败(如碎片化) - 对象被意外释放后未置空 --- ### 调试建议 1. **检查对象创建逻辑**: - 确认 `main_container` 的第10个子对象初始化流程 - 验证 `lv_obj_create()` 后是否调用了 `lv_obj_init_spec_attr()` 2. **增强空指针检查**: ```c // 修改 TpMenu.c:464 的调用 lv_obj_t* target = lv_obj_get_child(lv_obj_get_child(...)); if(target && target->spec_attr) { // 增加双重校验 lv_image_set_src(target, ...); } ``` 3. **内存完整性检测**: - 使用 `valgrind` 检查内存操作错误 - 开启LVGL的 `LV_USE_MEM_MONITOR` 监控内存分配 4. **复现路径**: - 在 `main_menu_event_cb` 设置断点 - 监控 `data->main_id` 变化,重点测试 `main_id=5`(10/2)的路径
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FikL919

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值