Xlib中XPutImage内部的奇怪分段错误

问题描述

我正在制作一个程序,该程序显示带有打开窗口中的图标的任务栏。我制作了一个函数,该函数需要两个指针和一些其他辅助数据。两个指针icon_Data和icon_Data_Ptr分别指向原子_NET_WM_ICON返回的数据,并指向我将要使用的特定图标。这是下面的功能

static pixmap create_pixmap_From_Icon_Data(Taskbar * taskbar,Taskbar_Item * taskbar_Item,uint32_t * icon_Data_Ptr,uint32_t * icon_Data) {
    pixmap icon_pixmap = XCreatepixmap(taskbar->display,taskbar->parent,(unsigned int) icon_Data_Ptr[0],(unsigned int) icon_Data_Ptr[1],32);

    XImage * x_Image = XCreateImage(taskbar->display,taskbar->visual,32,Zpixmap,2,(char *) &icon_Data_Ptr,0);

    GC temp_GC = XCreateGC(taskbar->display,icon_pixmap,0);

    XPutimage(taskbar->display,temp_GC,x_Image,icon_Data_Ptr[0],icon_Data_Ptr[1]);
    x_Image->data = (char *) icon_Data;

    XDestroyImage(x_Image);
    XFreeGC(taskbar->display,temp_GC);

    return icon_pixmap;
}

每当我尝试运行该程序时,它就会在一半的时间内出现段错误。来自Gdb的堆栈跟踪如下:

#0  __memmove_sse2_unaligned_erms ()
    at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:262
#1  0x00007ffff7c9f6b0 in memcpy (__len=<optimized out>,__src=0x7fffffffdd48,__dest=<optimized out>)
    at /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34
#2  SendZImage (dest_scanline_pad=<optimized out>,dest_bits_per_pixel=32,req_yoffset=0,req_xoffset=<optimized out>,image=0x459dd0,req=<optimized out>,dpy=0x4062a0)
    at ../../src/Putimage.c:795
#3  PutimageRequest (gc=<optimized out>,dest_scanline_pad=<optimized out>,req_height=<optimized out>,req_width=<optimized out>,y=<optimized out>,x=<optimized out>,d=<optimized out>,dpy=0x4062a0) at ../../src/Putimage.c:861
#4  PutSubImage (dpy=0x4062a0,gc=<optimized out>,req_yoffset=<optimized out>,x=0,y=0,req_width=48,req_height=48,dest_scanline_pad=32)
    at ../../src/Putimage.c:899
#5  0x00007ffff7c9faae in XPutimage (dpy=0x4062a0,d=23068677,gc=0x459e60,req_xoffset=0,req_height=48)
    at ../../src/Putimage.c:1018
#6  0x00000000004022bc in create_pixmap_From_Icon_Data (
    taskbar=0x4088e0,taskbar_Item=0x413760,icon_Data_Ptr=0x4579b8,icon_Data=0x413890) at taskbar.c:206
#7  0x0000000000402032 in find_And_Set_pixmap_From_Property_Data
    (taskbar=0x4088e0,icon_Data=0x413890,item_Count=72012) at taskbar.c:231
#8  0x0000000000401c48 in set_Taskbar_Item_Icon_pixmap (
    taskbar=0x4088e0,instance=0x408860)
    at taskbar.c:256
#9  0x000000000040196c in add_Instance_To_New_Taskbar_Item (
    taskbar=0x4088e0,instance=0x408860) at taskbar.c:315
#10 0x000000000040170e in add_Window_If_Necessary (
--Type <RET> for more,q to quit,c to continue without paging--
    taskbar=0x4088e0,window=18876630) at taskbar.c:386
#11 0x0000000000402ae5 in iterate_Through_All_Windows (
    taskbar=0x4088e0,display=0x4062a0,screen=0,iterator_Callback=0x401690 <add_Window_If_Necessary>)
    at taskbar_Test.c:31
#12 0x0000000000402997 in setup_Taskbar (taskbar=0x7fffffffdfb8,parent=23068674,visual=0x408430,colormap=23068673) at taskbar_Test.c:42
#13 0x00000000004027bf in main () at taskbar_Test.c:72

在其他时间调试过它时,我检查以确保icon_Data_Ptr具有足够的数据供XCreatepixmap运行。但是,奇怪的是,我发现当Gdb进入XCreatepixmap的内部时,指向函数内数据的指针与函数外的地址是不同的地址。另外,在使用GDB时,我发现当我在XCreateImage中时,图像的数据指针没有包含足够的数据来使函数正常工作。我还在XCreateImage的函数调用和XCreateImage的函数调用内部转储了指向图像数据的内存。我使用Gimp导入了此数据。该图片看起来像功能外部的chrome浏览器图标,但功能内部却看起来像是有序颜色和随机颜色的混合体,与chrome图标并不相似。

除了使用Gdb之外,我还尝试使用Clang代替GCC来查看这是否是编译器错误;它产生了相同的错误

我不知道自己在做错什么导致此细分错误,我们将为您提供任何帮助。

解决方法

我使用GDB遍历了机器代码,并在对XCreateImagelea -0x38(%rbp),%rdi的函数调用之前看到了这一点。这会将位于红色区域中的局部变量的地址加载到rdi寄存器中,随后根据Amd64的System V ABI({{ 3}})。因此,这意味着我没有传递指针值r9,而是传递了指针存储位置的地址:icon_Data_Ptr。这导致将错误的XImage结构传递给XPutImage,并导致分段错误。