C 分段故障(堆芯转储):从函数返回时出错

C 分段故障(堆芯转储):从函数返回时出错,c,segmentation-fault,return,C,Segmentation Fault,Return,我有两个功能 struct logger_message vget_log_msg(enum LogStatus log_status, const char* format, va_list args) { struct logger_message log_msg; log_msg.status = log_status; log_msg.timestamp = get_current_timestamp(); memset(log_msg.mess

我有两个功能

struct logger_message vget_log_msg(enum LogStatus log_status, const char* format, va_list args) {    
    struct logger_message log_msg;
    log_msg.status = log_status;
    log_msg.timestamp = get_current_timestamp();

    memset(log_msg.message_buffer, 0, MESSAGE_SIZE);
    if(format){    
        vsprintf(log_msg.message_buffer, format, args);
    }
    return log_msg;
}

因此,我在第行从vget_log_msg返回时得到错误“Segmentation Fault(Core dumped)”:

msg = vget_log_msg(log_status, format, argp);
编辑:也许这些信息很有用

struct logger_message{
    enum LogStatus status;
    time_t timestamp;
    char message_buffer[MESSAGE_SIZE];    
};

有人知道我为什么会犯这个错误吗?如何更正它?

我猜您使用了
vget\u log\u msg
,但没有在包含
send\u log\u message\u to\u mqueue
的文件中实际声明其原型。例如,通过不包括定义
vget\u log\u msg
的头文件,或者,如果两者在同一个文件中,通过在
发送\u log\u消息到\u mqueue
之前不定义
vget\u log\u msg

在这种情况下,编译器将假定
vget\u log\u msg
返回
int
,而不对返回结构的函数使用正确的调用约定。调用方在堆栈一侧为返回的结构分配缓冲区,并将指向该缓冲区的指针作为隐式参数传递给被调用函数,从而返回此类结构;然后,使用错误的调用约定将导致隐式指针丢失,从而导致错误,然后返回函数将返回的结构写入无效位置


或者,他们可以使用不同版本的
struct logger_message
,例如,包括声明不同的头文件。

我猜您使用的是
vget\u log\u msg
,而没有在包含
send\u log\u message\u to\u mqueue
的文件中实际声明其原型。例如,通过不包括定义
vget\u log\u msg
的头文件,或者,如果两者在同一个文件中,通过在
发送\u log\u消息到\u mqueue
之前不定义
vget\u log\u msg

在这种情况下,编译器将假定
vget\u log\u msg
返回
int
,而不对返回结构的函数使用正确的调用约定。调用方在堆栈一侧为返回的结构分配缓冲区,并将指向该缓冲区的指针作为隐式参数传递给被调用函数,从而返回此类结构;然后,使用错误的调用约定将导致隐式指针丢失,从而导致错误,然后返回函数将返回的结构写入无效位置



或者,他们可以使用不同版本的
struct logger\u message
,例如,包括声明不同的头文件。

消息大小是多少?那有多大?您可以通过减小消息的大小来检查,或者使用指针而不是整个结构返回消息。

消息的大小是多少?那有多大?您可以通过减小它的大小进行检查,或者使用指针而不是整个结构返回。

编译时是否使用
-Wall
?你收到警告了吗?是的,当然。编译项目时,我没有收到任何警告或错误。是否可能是
vsprintf()
正在从消息缓冲区的末尾退出?如果是的话,你有没有考虑改用?既然您已经有了缓冲区大小,为什么不使用它呢。希望您的工具链和运行时与C99或更高版本兼容,我相信这是它第一次出现在我们这里的时候。您在编译时是否使用
-Wall
?你收到警告了吗?是的,当然。编译项目时,我没有收到任何警告或错误。是否可能是
vsprintf()
正在从消息缓冲区的末尾退出?如果是的话,你有没有考虑改用?既然您已经有了缓冲区大小,为什么不使用它呢。希望您的工具链和运行时与C99或更高版本兼容,我相信这是它第一次出现在我们这里时的情况。我正在尝试考虑任何现代编译器(在过去十年左右),它不标记来自未声明函数的此类赋值(从而假设
int
返回值)当返回除值以外的任何值时,如果该值至少可以尝试将
int
保留并强制为正在使用的左值,则会出现错误。例如:如果不声明函数,OP的代码将导致编译错误,声明“错误:
struct logger\u message
int
是不兼容的类型。”虽然您认为point对于来自
int
的可强制类型(特别是指针)非常有效,但我不确定它在这里是否有效。足够正确。我添加了另一种解释。不。如果你试图将“int”赋值给一个结构,任何一个好的编译器都会出错。原型在头文件中声明,头文件也包含在内。所以建议是行不通的。我试着想想(在过去十年左右)任何现代编译器,它不标记来自未声明函数的赋值(从而假设
int
返回值)当返回除值以外的任何值时,如果该值至少可以尝试将
int
保留并强制为正在使用的左值,则会出现错误。例如:如果不声明函数,OP的代码将导致编译错误,声明“错误:
struct logger\u message
int
是不兼容的类型。”虽然您认为point对于来自
int
的可强制类型(特别是指针)非常有效,但我不确定它在这里是否有效。足够正确。我添加了另一种解释。不。如果你试图将“int”赋值给一个结构,任何一个好的编译器都会出错。原型在头文件中声明,头文件也包含在内。所以建议不起作用,没错。不幸的是,消息大小等于24,太小了。谢谢,没错。不幸的是,消息大小等于24,太小了。非常感谢。
struct logger_message{
    enum LogStatus status;
    time_t timestamp;
    char message_buffer[MESSAGE_SIZE];    
};