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];
};