我在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会传递在堆栈上,但 int
和 double
的尺寸不同。
为FP ARGS编写0.0
将使隐式声明与定义匹配。但不要这样做,调用未宣布的函数仍然是一个可怕的主意。使用-Wall
让编译器告诉您何时代码做坏事。
您的功能可能仍会崩溃;谁知道您在代码中还有哪些错误?
当您的代码崩溃时,您应该查看其崩溃的ASM指令,以找出哪个指针不好 - 例如在GDB中运行disas
。即使您自己不了解它,包括在调试 - 霍尔普问题(以及寄存器值)中也可能有所帮助。