Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C-变量函数编译,但给出了分段错误_C_Variadic_X86 - Fatal编程技术网

C-变量函数编译,但给出了分段错误

C-变量函数编译,但给出了分段错误,c,variadic,x86,C,Variadic,X86,我在C中有一个变量函数,可以写入日志文件,但一旦调用它,它就会在头中出现分段错误 在主进程中,调用具有以下格式: mqbLog("LOG_INFORMATION",0,0,"Connect",0,"","Parameter received"); 函数的定义如下: void mqbLog(char *type, int numContext, double sec, char *service,

我在C中有一个变量函数,可以写入日志文件,但一旦调用它,它就会在头中出现分段错误

在主进程中,调用具有以下格式:

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,因此它传递的是一个整数,被调用方期望一个双精度

从指针值判断,这可能是在x86-64 Linux上,使用System V调用约定,其中为arg分配的寄存器由它决定,例如,第三个整数arg。有关ABI/调用约定文档,请参见wiki

因此,如果调用者和被调用者对函数签名不一致,他们将对哪个参数进入哪个寄存器不一致,我认为这解释了为什么gdb显示与调用者不匹配的参数

在本例中,调用方将Connect地址放入RCX中,因为它是带有该隐式声明的第四个整数/指针arg

调用者在RDX中查找服务的值,因为其调用者的第三个整数/指针arg

被调用方的sec为0.0显然是偶然的。它只是使用XMM0中的任何东西。或者可能是未初始化的堆栈空间,因为调用者会将AL=0设置为指示没有FP args传入仅用于可变函数的寄存器。注al=原型可用时,fp寄存器参数的数量包括固定的非可变参数。使用可用的原型编译您的呼叫包括一个mov eax,1在呼叫之前。有关使用/不使用原型进行编译的信息,请参阅source+asm

在另一种调用约定中,例如使用堆栈args的-m32,情况至少会严重中断,因为这些args将在堆栈上传递,但int和double的大小不同

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

您的函数可能仍然会崩溃;谁知道代码中还有哪些未显示的bug


当您的代码崩溃时,您应该查看它崩溃的asm指令,以确定哪个指针是坏的-例如,在gdb中运行disas。即使您自己不了解它,在调试帮助问题中包括它以及寄存器值也会有很大帮助。

您在实现该函数时遇到了一个错误。我建议从阅读相关手册开始。给我们足够的代码来复制错误。函数的声明在哪里?您的调用依赖于原型范围内0到0.0的隐式转换。省略调用函数的原型本质上是未定义的行为;在调用变量函数之前,必须始终在作用域中有一个原型。您的函数正在崩溃,但您尚未展示如何实现该函数。您希望我们如何帮助您调试它?有很多事情你可能做错了;其中许多可能导致撞车。请包含一个复制崩溃的MCVE。您可以看到sizeData未对齐,这更像是某个指针0x402099。如果这个函数是在不同的翻译单元中声明的,我的猜测是声明与定义不一致。请尝试将3.14之类的代码传递一秒,然后再次调试。但首先,在编译程序时启用所有警告。@PeterCordes:GDB所遇到的问题表明了这些方面的问题。我宁愿从OP那里得到信息,但你的推断可能是正确的。谢谢彼得!我做了您列出的更改,完美地完成了双数duh,函数声明。对不起,如果我之前不能回答,昨天是混乱的一天D: