C- variadic函数编译,但给出了分割故障



我在c中具有variadic函数要在日志文件中写入,但是一旦调用它,它就会在标题中给出一个分割故障。

在主过程中,呼叫具有此格式:

mqbLog("LOG_INFORMATION",0,0,"Connect",0,"","Parameter received");  

和该函数是这样定义的:

void mqbLog(char *type,
            int  numContext,
            double sec,
            char *service,
            int   sizeData,
            char *data,
            char *fmt,
            ...
            )
{  
    //write the log in the archive
}

它编译确定。当我调试过程时,对mqbLog函数的调用已完成,它使我在函数的开放括号中的分段故障,因此我可以询问函数值:

(gdb) p type
$1 = 0x40205e "LOG_INFORMATION"
(gdb) p numContext
$2 = 0
(gdb) p sec
$3 = 0
(gdb) p service
$4 = 0x0
(gdb) p sizeData
$5 = 4202649
(gdb) p data
$6 = 0x0

任何想法都会非常感激。

基于GDB输出,看来呼叫者没有针对其调用功能的原型。正如@jonathanleffler所注意到的那样,您写了0,而不是0.0,因此它通过了一个整数,CALLEE期望double


从指针值来判断,这可能是在X86-64 Linux上使用System v调用约定的Linux上的,其中为ARG分配的寄存器由其确定为例如。第三 Integer arg。(有关ABI/呼叫大会文档,请参见x86 Wiki)。

因此,如果呼叫者和Callee对函数签名不同意,他们将不同意ARG在哪个登记册中,我认为这解释了GDB为何显示GDB显示与呼叫者不匹配的ARG。


在这种情况下,呼叫者将"Connect"(地址)放在RCX中,因为它是带有该隐式声明的第四个整数/指针ARG。

呼叫者在rdx中寻找service的值,因为其呼叫者的第三个整数/指针arg。

sec显然是偶然的。它只是使用XMM0中的任何东西。也许可能是非初始化的堆栈空间,因为呼叫者将设置AL=0以表明在寄存器中没有传递FP ARG(仅对于Variadic函数所需)。注意al = FP寄存器ARGS的数量包括固定的非Variadic args,当可用时。用编译您的呼叫可用的原型包括call之前的mov eax, 1。请参阅源 ASM,以使用/不使用Godbolt编译器资源管理器上的原型编译。

在不同的调用惯例(例如 -m32带有stack args)中,由于这些args会传递在堆栈上,但 intdouble的尺寸不同。


为FP ARGS编写0.0将使隐式声明与定义匹配。但不要这样做,调用未宣布的函数仍然是一个可怕的主意。使用-Wall让编译器告诉您何时代码做坏事。

您的功能可能仍会崩溃;谁知道您在代码中还有哪些错误?


当您的代码崩溃时,您应该查看其崩溃的ASM指令,以找出哪个指针不好 - 例如在GDB中运行disas。即使您自己不了解它,包括在调试 - 霍尔普问题(以及寄存器值)中也可能有所帮助。

最新更新