调用gtk_main_quit导致"分段错误"在汇编代码中

时间:2016-03-26 12:01:58

标签: assembly segmentation-fault gtk gtk3

我学习汇编程序(FASM)并且我遇到了奇怪的问题,每当我想调用gtk_main_quit()时,它总是以"分段错误"结束。

为什么调用gtk_main_quit会导致分段错误?

TEST.ASM

format ELF

extrn gtk_init
extrn gtk_main
extrn gtk_main_quit
extrn gtk_window_new
extrn gtk_widget_show
extrn g_signal_connect_data

public main

on_window_close:
    call gtk_main_quit ; <- segmentation fault
    ret

main:
    push 0
    push 0
    call gtk_init
    add esp, 8

    push 0
    call gtk_window_new
    add esp, 4
    mov [window_handle], eax

    push 0
    push 0
    push 0
    push on_window_close
    push on_close_signal
    push [window_handle]
    call g_signal_connect_data
    add esp, 24

    push [window_handle]
    call gtk_widget_show
    add esp, 8

    call gtk_main

window_handle dd 0
on_close_signal db 'destroy', 0

生成文件

all:
    ~/apps/fasm/fasm ./test.asm
    gcc -o test test.o `pkg-config --cflags --libs gtk+-3.0`

2 个答案:

答案 0 :(得分:4)

进行函数调用时,请务必确保在调用后正确恢复堆栈。您的代码执行此操作:

push [window_handle]
call gtk_widget_show
add esp, 8

您将一个 DWORD 作为参数正确地推送到堆栈上,但在致电gtk_widget_show后,您将 ESP 添加8。由于您只在堆栈上推送了4个字节,因此无法正确恢复 ESP 。副作用是函数main的返回地址现在将位于错误的位置,这可能会在main函数返回时产生分段错误。代码应该是:

push [window_handle]
call gtk_widget_show
add esp, 4

这引出了第二个问题。你的代码:

    call gtk_main

window_handle dd 0
on_close_signal db 'destroy', 0

gtk_main返回后,它将开始执行后面出现在内存中的任何指令。在这种情况下,它恰好是一些变量和内存中的其他任何变量。由于 C 运行时调用函数main与任何其他函数一样,您应该使用ret返回 C 运行时并让它关闭你的程序干净利落。

代码如下:

    call gtk_main
    ret

window_handle dd 0
on_close_signal db 'destroy', 0

答案 1 :(得分:1)

gtk_main_quit的调用导致gtk_main返回,在执行窗口句柄的调用之后继续执行,并且可能是文本&#34; destroy&#34;。很难准确预测会发生什么。

ret之后添加call gtk_main