【问题标题】:Random core dumps随机核心转储
【发布时间】:2022-01-03 00:41:50
【问题描述】:

我在写一个项目,里面有两个程序,客户端和服务端,客户端向服务端发送一个字符串,服务端处理后返回给客户端(可以同时有多个客户端,这就是我的问题所在)。我在需要处理的相同字符串中从客户端发送进程 ID,服务器提取进程 ID。但是我得到了随机的核心转储,这些转储不一致。大多数时候它工作正常。它发生在调用strtol() 调用receive_message(...) 函数之前。

服务器receive_message(...)函数:

int receive_message(struct message *x){
    int ret_val, z;
    ret_val = msgrcv(msg_q_id, x, MAX, 0, 0);
    if (ret_val == -1){
        if (signal_detection == 1){
            exit(0);
        }
    perror("COULDNT receive a message!");
        exit(-1);
    } else {
    int c = 0;
        while (x->mtext[c] != '!'){
            ++c;
        }
    int h = c;
        char tab[strlen(x -> mtext) - c];
        int s = 0;
        for (int counter = c + 1; counter < strlen(x->mtext); ++counter){
            tab[s++] = x->mtext[counter];
        }
    printf("\n%s\n", tab);
        z = strtol(tab, NULL, 10);
        memset((x -> mtext) + h, 0, strlen(x -> mtext) - 1 - c);
        printf("message received: %s\n", x -> mtext);
    }
    return z;
}

整个服务器代码:

#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <signal.h>

#define MAX 255
#define CLIENT 1
#define SERVER 2

int signal_detection = 0;
int msg_q_id;
key_t msg_q_key;
struct message;

void create_queue();
void send_message(struct message *x, int pid);
int receive_message(struct message *x);
void delete_message_q();
void to_upper_case(struct message *x);
void signal_handler(int signum, siginfo_t *info, void *ptr);

struct message{
    long int mtype;
    char mtext[MAX];
};

int main(){
    struct message member_of_message;
    struct message *ptr;
    struct sigaction sig;
    int sig_ret;
    ptr = &member_of_message;
    sig.sa_sigaction = signal_handler;
    sig_ret = sigaction(SIGINT, &sig, NULL);
    if (sig_ret == -1){
        perror("sigaction fail");
    }
    create_queue();
    while (1){
    int pid;
        memset(member_of_message.mtext, 0, strlen(member_of_message.mtext));
        printf("waiting for message\n");
        pid = receive_message(ptr);
        to_upper_case(ptr);
        printf("After uppering: %s\n", member_of_message.mtext);
        send_message(ptr, pid);
        sleep(1);
    }
}

void create_queue(){
    printf("starting to create queue\n");
    msg_q_key = ftok(",", 4);
    msg_q_id = msgget(msg_q_key, 0700|IPC_CREAT);
    if (msg_q_id == -1){
        perror("COULDNT create msgq");
        exit(-1);
    } else {
    printf("succesfully created: %d !\n", msg_q_id);
    }
}

void send_message(struct message *x, int pid){
    int ret_val;
    x -> mtype = pid + 1;
    wysylanie:
    ret_val = msgsnd(msg_q_id, x, strlen(x -> mtext) + 1, 0);
    if (ret_val == -1){
        if (errno == EAGAIN){
                perror("message queue is full!");
                goto wysylanie;
        }
    perror("COULDNT send a message");
        exit(-1);
    } else {
    printf("message sent!\n");
    }
}

int receive_message(struct message *x){
    int ret_val, z;
    ret_val = msgrcv(msg_q_id, x, MAX, 0, 0);
    if (ret_val == -1){
        if (signal_detection == 1){
            exit(0);
        }
    perror("COULDNT receive a message!");
        exit(-1);
    } else {
    int c = 0;
        while (x->mtext[c] != '!'){
            ++c;
        }
    int h = c;
        char tab[strlen(x -> mtext) - c];
        int s = 0;
        for (int counter = c + 1; counter < strlen(x->mtext) - 1; ++counter){
            tab[s++] = x->mtext[counter];
        }
    printf("\n%s\n", tab);
        z = strtol(tab, NULL, 10);
        memset((x -> mtext) + h, 0, strlen(x -> mtext) - 1 - c);
        printf("message received: %s\n", x -> mtext);
    }
    return z;
}

void delete_message_q(){
    int ret_val;
    ret_val = msgctl(msg_q_id, IPC_RMID, 0);
    if (ret_val == -1){
        perror("COULDNT remove message queue");
        exit(-1);
    } else {
    printf("message queue deleted!\n");
    }
}

void to_upper_case(struct message *x){
    for (int counter = 0; counter < strlen(x->mtext); ++counter){
        x->mtext[counter] = toupper(x->mtext[counter]);
    }
}

void signal_handler(int signum, siginfo_t *info, void *ptr){
    signal_detection = 1;
    printf("\nReceived a signal!\nstopping iteration\n");
    delete_message_q();
}

客户端代码:

#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <string.h>

#define MAX 255
#define CLIENT 1
#define SERVER 2
#define M_SENT 3

int msg_q_id;
key_t msg_q_key;
struct message;
int pid;
void create_queue();
void *send_message();
void *receive_message(void *arg);

struct message{
    long int mtype;
    char mtext[MAX];
};

int main(){
    struct message member_of_message;
    struct message *ptr;
    int thread_val;
    ptr = &member_of_message;
    pthread_t pid1, pid2;
    create_queue();
    sleep(1);
    printf("creating thread1......\n");
    thread_val = pthread_create(&pid1, NULL, send_message, NULL);
    if (thread_val != 0){
        perror("couldnt create thread");
        exit(-1);
    }
    printf("creating thread2......\n");
    thread_val = pthread_create(&pid2, NULL, receive_message, ptr);
    if (thread_val != 0){
        perror("couldnt create thread");
        exit(-1);
    }
    thread_val = pthread_join(pid1, NULL);
    if (thread_val != 0){
        perror("couldnt create thread");
        exit(-1);
    }
    thread_val = pthread_join(pid2, NULL);
    if (thread_val != 0){
        perror("couldnt create thread");
        exit(-1);
    }
}

void create_queue(){
    printf("starting creation of a queue\n");
    msg_q_key = ftok(",", 4);
    msg_q_id = msgget(msg_q_key, 0700|IPC_CREAT);
    if (msg_q_id == -1){
        perror("COULDNT create msgq");
        exit(-1);
    } else {
    printf("succesfully created: %d !\n", msg_q_id);
    }
}

void *send_message(){
    int last_val;
    struct message member_of_message;
    int ret_val;
    char rub[10000];
    for (int message_counter = 0; message_counter < M_SENT; ++message_counter){
        pid = getpid();
        member_of_message.mtype = pid;
        char arr[MAX];
        if (fgets(arr, MAX - 20, stdin) == NULL){
            perror("not a single char read, message sent is empty");
        }
    if (strlen(arr) == 1){
            perror("cannot send empty message!");
            exit(-1);
        }
    if (strchr(arr, '\n') == NULL){
            perror("Przepelniono komunikat!");
            fgets(rub, 10000, stdin);
        }
    char temp_arr[20];
        int sp_retval;
        sp_retval = sprintf(temp_arr, "%d", pid);
        if (sp_retval == 0){
            perror("0 bytes read");
            exit(-1);
        }
    for (int counter = 0; counter < strlen(arr) - 1; ++counter){
            member_of_message.mtext[counter] = arr[counter];
            last_val = counter;
        }
member_of_message.mtext[last_val + 1] = '!';
        strcat(member_of_message.mtext, temp_arr);
        wysylanie:
        ret_val = msgsnd(msg_q_id, (struct message*)&member_of_message, strlen(member_of_message.mtext), 0);
        if (ret_val == -1){
            if (errno == EAGAIN){
                perror("message queue is full!");
                goto wysylanie;
            }
            perror("COULDNT send a message");
            exit(-1);
        } else {
        printf("message sent!, PID: %d \n", pid);
        memset(member_of_message.mtext, 0, strlen(member_of_message.mtext));
        }
    }
}

void *receive_message(void *arg){
    int ret_val;
    for (int message_counter = 0; message_counter < M_SENT; ++message_counter){
        sleep(1);
        ((struct message*)arg)->mtype = pid + 1;
        ret_val = msgrcv(msg_q_id, (struct message*)arg, MAX, ((struct message*)arg)->mtype, 0);
        if (ret_val == -1){
            perror("COULDNT receive a message!");
            exit(-1);
        } else {
        printf("message received: %s\n", ((struct message*)arg)->mtext);
        memset(((struct message*)arg)->mtext, 0, strlen(((struct message*)arg)->mtext));
        }
    }
}

【问题讨论】:

  • 是否缺少tab[s] = '\0'
  • @KamilCuk 试过了,核心转储仍然存在;/
  • 这一行:ret_val = msgsnd(msg_q_id, (struct message*)&amp;member_of_message, strlen(member_of_$ 无法编译。剪切/粘贴代码时请使用换行。
  • @EmployedRussian 对,我编辑了,谢谢指出!
  • 无论如何,用-Wall -Wextra -fsanitize=undefined,address -g3 编译并等待错误。它很可能会解决大多数问题。

标签: c linux gcc struct message-queue


【解决方案1】:
ret_val = msgsnd(msg_q_id, (struct message*)&member_of_message, strlen(member_of_message.mtext), 0);

这一行最清楚地显示了这段代码的问题。您正在发送由消息类型和消息文本组成的消息消息的大小不可能等于消息文本的长度,因为还需要发送一定数量的字节来保存消息类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 2017-08-13
    • 2021-02-16
    相关资源
    最近更新 更多