在调用msgrcv()后,我得到了一个E2BIG:在SunOS,CPP编译器上。
输出如下:
arguments:
MsgID: 335006
pointer: 0xffbfbac8
sizeof: 1040
MsgType: 0
MsgFlag: 2048
RetVal=-1
RM: message waiting failed with error 7.
在手册中:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
Maunal对于msgrcv()说,当“消息文本长度大于msgsz且未在msgflg中指定MSG_NOERROR时”获得E2BIG。
但在我的情况下,看起来长度等于msg文本。顺便说一句,这个函数如何得到void * msgp的长度?这是一个空白。
抱歉,我发布了一段很长的代码,因为我害怕错过一些东西。 感谢。
修改
手册说,
The msgp argument is a pointer to caller-defined structure of the fol-
lowing general form:
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
The mtext field is an array (or other structure) whose size is specified by msgsz, a non-negative integer value
我按照以下方式添加gdb的更多信息: 227 RetVal = msgrcv(TDM_M [MyModule] .msg_id, 228(void *)& SysMsg, 229(size_t)sizeof(T_MSGBUF), 230 MsgType, 231 MsgFlag); 23 235 * / (gdb)p sizeof(SysMsg) 10美元= 1044美元 (gdb)p sizeof(T_MSGBUF) $ 11 = 1040
长度 - 目标的大小= 4(=长整数的大小),看起来是正确的。 另外,我发现问题只发生在SunOS上。相同的代码在Linux上运行良好。
编辑我找到了根本原因。就像errno E2BIG指示MsgLength小于收到的消息一样,我的发送宏计数一个错误的值,该值应该等于WAIT_MSG()中的MsgLength。
感谢您的建议和解答。
.h文件 / * MSGBUF是针对特定消息定义的 * SysMsg定义为msgrcv的arg * /
#define MSGBUF_SIZE 1040
#define MSGBODY_SIZE (MSGBUF_SIZE)
#define MSGBODY_SIZE1 (MSGBUF_SIZE-16)
typedef struct {
unsigned char SrcModule;
unsigned char DstModule;
unsigned char MsgType;
unsigned short SubMsgId;
unsigned short Length;
long int reserved;
} MsgHeader;
typedef struct _MsgBody {
unsigned char Data[MSGBODY_SIZE1];
} MSGBODY;
typedef struct _MsgBuf {
MsgHeader Header; // the header of message.
MSGBODY Body; // the message body.
} MSGBUF;
typedef struct _MsgInside {
long int MsgType;
MSGBUF MsgText;
} SYS_MSG;
的.cpp
int WaitMsg (DMMODULE MyModule,
MSGBUF* pMsgBuf,
long MsgType,
int MsgFlag,
TIME_USEC abs_timeout)
{
SYS_MSG SysMsg;
int RetVal;
...
memset(&SysMsg, 0, sizeof(SYS_MSG));
printf("arguments:\n");
printf("MsgID: %d\n", Module[MyModule].msg_id);
printf("pointer: 0x%x\n", (void *)&SysMsg);
printf("sizeof: %d\n", (size_t)sizeof(T_MSGBUF));
printf("MsgType: %d\n", MsgType);
printf("MsgFlag: %d\n", MsgFlag);
/* Module is a global array in which msg_id is storing */
RetVal = msgrcv( Module [MyModule].msg_id,
(void *)&SysMsg,
(size_t)sizeof(MSGBUF),
MsgType,
MsgFlag);
/* So far, only ENOMSG is handled, the rest is ignored,
* Maybe a signal handler is needed later.
*/
if( RetVal == -1 )
{
switch (errno)
{
case ENOMSG:
return My_ENOMSG;
case E2BIG:
case EACCES:
case EAGAIN:
case EFAULT:
case EIDRM:
case EINTR:
case EINVAL:
/* Here is where the error reported */
printf("%s: message waiting failed with error %d.\n",
Module[MyModule].name, errno);
printf("%s: \n", strerror(errno));
return FAIL;
default:
printf("%s: message waiting failed with error %d.\n",
Module[MyModule].name, errno);
printf("%s: \n", strerror(errno));
return FAIL;
}
}
memcpy(pMsgBuf, &(SysMsg.MsgText), sizeof(T_MSGBUF));
printf("message is received by %s.\n", Module[MyModule].name);
return SUCC;
}
...
#define WAIT_MSG(MyModule,pMsgBuf,time_us ) \
WaitMsg((MyModule),(pMsgBuf),0,IPC_NOWAIT,0)
int main()
{
int rc = -1;
MSGBUF msgbuf;
rc = WAIT_MSG( RM, &msgbuf, 0 );
...
}
}
答案 0 :(得分:1)
错误E2BIG
表示您尝试接收的邮件不适合您的缓冲区。你必须让缓冲区更大。你的缓冲区大约是1020或1024字节,我不确定。如果传入的消息较大,则会获得E2BIG
。
顺便说一下,这个函数如何得到void * msgp的长度?这是一个空白。
看起来你对指针的工作原理有点不清楚。指针只指向内存中的单个位置,它们没有长度。 (即使非void指针也没有“长度”。)无论何时指定内存区域,都必须指定其起始位置(void *
)及其长度(size_t
)。将一系列内存传递给C中的函数时,通常以三种方式之一指定长度:
setjmp
时,会将指针传递给内存区域sizeof(jmp_buf)
字节长。fwrite
或msgrcv
。strlen
。<强>建议:强>
void *
,请不要使用强制转换;如果您不小心将非指针强加到void *
,这可以隐藏代码中的错误。必要时,指针会自动转换为void *
。sizeof
的结果始终是size_t
,不要施展它。这就像写(int)1
,(double)0.5
或(const char [6])"Hello"
。请勿将sizeof(type)
用于memcpy
或msgrcv
个参数。 memcpy
参数中的错别字是错误的常见来源,并且引用远程类型使得在阅读代码时更难发现它们。
// Not so good
// Reading the code, I have to look for the definition of pMsgBuf
// in order to know if sizeof(T_MSGBUF) is correct
memcpy(pMsgBuf, &(SysMsg.MsgText), sizeof(T_MSGBUF));
// Who knows if sizeof(MSGBUF) is correct?
msgrcv(..., &SysMsg, sizeof(MSGBUF), ...);
// Better
// Reading the code, I know sizeof(*pMsgBuf) is correct,
// but &(SysMsg.MsgText) might be a different type.
memcpy(pMsgBuf, &(SysMsg.MsgText), sizeof(*pMsgBuf));
msgrcv(..., &SysMsg, sizeof(SysMsg), ...);
// Best
// Most errors will be caught by the compiler.
static void msgbuf_copy(MSGBUF *dest, const MSGBUF *src)
{ memcpy(dest, src, sizeof(*dest)); }
msgbuf_copy(pMsgBuf, &SysMsg.MsgText);
如果您希望消息为1024字节,请在代码中写入。不要组装恰好恰好加起来1024字节的结构,使其明确发生。
typedef struct {
unsigned char SrcModule;
unsigned char DstModule;
unsigned char MsgType;
unsigned short SubMsgId;
unsigned short Length;
long int reserved;
} MsgHeader;
typedef struct {
MsgHeader Header;
char Body[1024 - sizeof(MsgHeader)];
} MSGBUF;
答案 1 :(得分:0)
传递给SysMsg
的变量msgrcv
的类型为
typedef struct _MsgInside {
long int MsgType;
MSGBUF MsgText;
} SYS_MSG;
你有没有尝试过愚蠢和简单的事情
typedef struct _MsgInside {
long int MsgType;
char MsgText[10000];
} SYS_MSG;
看它是否改变了它的行为?
编辑,ooops
此外,字段字段为sizeof(MSGBUF)
,但邮件的类型为SYS_MSG
充其量这令人困惑;始终使用sizeof(var)
。
答案 2 :(得分:0)
要计算正确的msgsz
,请执行sizeof(SysMsg) - sizeof(SysMsg.MsgType)
:您必须减去消息缓冲区的long mtype
字段。这也必须在发件人中完成。