我正在 Linux 中使用消息队列和信号编写多处理 C 程序。有时终端会弹出以下错误。
错误:
scheduler.out:malloc.c:2617:sysmalloc:断言`(old_top == initial_top(av)&& old_size == 0)|| ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' 失败。
代码:
Process* stringtoProcess(char* str) {
Process* p = malloc(sizeof(Process));
sscanf(str, "%d %d %d %d %d %d %d %s", &p->id, &p->arrival, &p->startTime, &p->runtime, &p->priority, &p->WaitingTime, &p->remainingTime, p->state);
return p;
}
void receiveProcess() {
key_t key_up, key_down;
int msgid_up, msgid_down;
struct msgbuf buffer_up, buffer_down;
key_up = ftok("keyfile", 'A');
key_down = ftok("keyfile", 'Z');
if (key_up == -1 || key_down == -1) {
perror("ftok");
exit(EXIT_FAILURE);
}
msgid_up = msgget(key_up, 0666 | IPC_CREAT);
msgid_down = msgget(key_down, 0666 | IPC_CREAT);
if (msgid_up == -1 || msgid_down == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
memset(&buffer_up, 0, sizeof(buffer_up));
memset(&buffer_down, 0, sizeof(buffer_down));
if (msgrcv(msgid_up, &buffer_up, sizeof(buffer_up.mtext), 5, !IPC_NOWAIT) == -1) {
perror("msgrcv");
exit(EXIT_FAILURE);
}
Process *p = stringtoProcess(buffer_up.mtext);
TotalRunTime += p->runtime;
if(FirstArrival == -1)
FirstArrival = p->arrival;
if(algo == 1)
enqueue(ready_queue, p);
else push(ready_queue, p, prio_flag);
buffer_down.mtype = 5;
if(msgsnd(msgid_down, &buffer_down, sizeof(buffer_down.mtext), 5) == -1) {
perror("msgsend");
exit(EXIT_FAILURE);
}
}
这是流程结构
typedef struct Process {
int id;
int pid;
int arrival;
int startTime;
int runtime;
int priority;
int WaitingTime;
int remainingTime;
char state[20];
int Sent;
} Process;
receiveProcess 函数是一个信号处理程序,会连续调用多次(大约 1 - 5 次)。经过一些调试,我发现这个错误是在第三次或第四次进入该函数时发生的。
请记住,通常它根本不会发生。
您的代码存在多个问题。
Process* stringtoProcess(char* str) {
Process* p = malloc(sizeof(Process));
sscanf(str, "%d %d %d %d %d %d %d %s", &p->id, &p->arrival, &p->startTime, &p->runtime, &p->priority, &p->WaitingTime, &p->remainingTime, p->state);
return p;
}
这里有两个问题。您没有检查
malloc()
是否成功,而是将未初始化的内存写入 str
。
如果我们将自己局限于 ISO C 标准,那么在信号处理程序中可以做的事情就很少了。但是,您的代码假定 POSIX 支持,因此我不会详细介绍。与 C 标准不同,POSIX 标准指定了很多函数为 async-signal-safe,但是
ftok()
、perror()
、exit()
、msgget()
、msgrcv()
、malloc()
、sscanf()
、 和 msgsnd()
不在其中。
函数
enqueue()
和 push()
也可能是异步信号不安全的。请注意,信号处理程序本身调用的函数不应调用异步信号不安全函数,这与 stringtoProcess()
不同,它调用 malloc()
和 sscanf()
。
信号处理程序的签名是:
typedef void (*sighandler_t)(int);
你的
receiveProcess()
功能不符合它。
您忽略了
sscanf()
的返回值,并且使 Process
结构体的两个成员未初始化。