首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >执行开始时的分段错误

执行开始时的分段错误
EN

Stack Overflow用户
提问于 2017-02-12 21:04:05
回答 1查看 237关注 0票数 1

我正在尝试理解类unix系统中的IPC机制。编译后,我无法运行我的程序,因为它在执行任何操作之前都会崩溃(甚至无法在main()中打印第一行)并得到分段错误。

万一您想知道这里发生了什么: dispatcher是一个程序,它存储由工厂产生的消息,并根据它们的需求将它们分配给客户端进程。

我使用的是Mint 18和4.4通用内核。

dispatcher.c代码:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>

#include "booth.h"

typedef struct message_queue{
    pid_t *clients_served;
    message msg;
    struct message_queue *next;
} message_queue;

int stop = 0;
static message *msg = NULL;
message_queue message_vector[INT_MAX];
unsigned int number_of_clients = 0;
static pid_t *clients_list = NULL;

message_queue* new_queue_element(){
    int i;
    message_queue *new_element = malloc(sizeof(message_queue));

    memcpy(&new_element->msg, msg, sizeof(message_queue));
    new_element->clients_served = malloc(number_of_clients*sizeof(number_of_clients));
    // new_element->msg = *msg;
    new_element->next = NULL;
    for(i = 0; i < number_of_clients; i++){
        new_element->clients_served[i] = 0;
    }

    return new_element;
}

void append_queue(){
    int index;
    printf("Appending with message with id: %d\n", msg->id);
    message_queue *new_element = new_queue_element();
    index = new_element->msg.type;

    if(&message_vector[index] == NULL){
        message_vector[index] = *new_element;
    }
    else {
        message_queue *mq = &message_vector[index];
        while(mq->next != NULL){
            mq = mq->next;
        }
        mq->next = new_element;
    }
}

void show_queue(){
    int i = 0;
    message_queue *mq;
    for(i = 0; i < INT_MAX; i++){
        printf("message type: %d\n", i);
        mq = &message_vector[i];
        while(mq != NULL){
            printf("ID: %d, contents: %s\n", mq->msg.id, mq->msg.contents);
            mq = mq->next;
        }
    }
}

void read_clients_pids(){
    FILE * fp;
    char * line = NULL;
    size_t len = 0;
    ssize_t read;
    int i = 0;

    fp = fopen("clients.txt", "r");
    if (fp == NULL)
        exit(1);

    // get number of clients
    while ((read = getline(&line, &len, fp)) != -1) {
        number_of_clients++;
    }

    fclose(fp);
    clients_list = (int*)malloc(number_of_clients * sizeof(unsigned int));

    fp = fopen("clients.txt", "r");
    if (fp == NULL)
        exit(1);

    // fill clients_list with clients PIDs
    i = 0;
    while ((read = getline(&line, &len, fp)) != -1) {
        clients_list[i++] = (pid_t) atoi(line);
    }

    fclose(fp);
    printf("Dispatcher will work with following clients:\n");
    for(i = 0; i < number_of_clients; i++)
        printf("%d\n", clients_list[i]);

    if (line)
        free(line);
}

void prepare_factory_shm(message **msg, key_t *key, int *shmid){
        get_factory_key(key);
    get_shmid(shmid, *key);
    attach(msg, *shmid);
}

void give_message_to_client(pid_t client){
    printf("Sending message to: %d\n", (int)client);
}

void signal_request_handler(int sig, siginfo_t *siginfo, void *context){
    /*
    SIGUSR1 is used for handling communication with factory
    SIGUSR2 is used for handling communication with clients.
        if number_of_clients equals to 0, we read new clients list.
        otherwise we give newest message still not read by client. If all messages have been read NULL is set
    SIGTERM sets stop variable to 1 break loop in main() and clean up mess.
    */
    if(sig == SIGUSR1){
        printf("SIGUSR1 received by: %d sent by: %d\n", getpid(), siginfo->si_pid);
        append_queue();
    }
    else if(sig == SIGUSR2){
        printf("SIGUSR2 received by process: %d\n", getpid());
        if(number_of_clients == 0){
            read_clients_pids();
        }
        else{
            give_message_to_client(siginfo->si_pid);
        }
    }
    else if(sig == SIGTERM){
        printf("SIGTERM received by: %d\n", getpid());
        stop = 1;
    }
}

void prepare_sigaction(){
    static struct sigaction factory_action;
    static struct sigaction client_action;
    static struct sigaction terminate_action;

    factory_action.sa_sigaction = *signal_request_handler;
    factory_action.sa_flags |= SA_SIGINFO;
    sigemptyset(&factory_action.sa_mask);
    sigaction(SIGUSR1, &factory_action, NULL);

    client_action.sa_sigaction = *signal_request_handler;
    client_action.sa_flags |= SA_SIGINFO;
    sigemptyset(&client_action.sa_mask);
    sigaction(SIGUSR2, &client_action, NULL);

    terminate_action.sa_sigaction = *signal_request_handler;
    terminate_action.sa_flags |= SA_SIGINFO;
    sigemptyset(&terminate_action.sa_mask);
    sigaction(SIGTERM, &terminate_action, NULL);
}

int main(int argc, char *argv[]){
  key_t key;
    int shmid;

    read_clients_pids();
    prepare_factory_shm(&msg, &key, &shmid);
    prepare_sigaction();

    // wait for termination signal
    while(!stop)
        ;

    // clean up
    show_queue();
  shmdt(msg);
    shmctl(shmid, IPC_RMID, NULL);
  exit(0);
}

booth.h代码:

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include<string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <fcntl.h>

#define BUFSIZE 1024
#define PERM    0644

typedef struct message{
    int id;
    int type;
    char contents[BUFSIZE];
    unsigned long len;
} message;

char *get_client_com_file_name(pid_t pid);
void prepare_client_com(pid_t pid);
void prepare_factory_com();
void inform_dispatcher(int dispatcher_id);
message message_request();
void get_client_key(key_t *key, pid_t client_pid);
void get_factory_key(key_t *key);
void get_shmid(int *shmid, const key_t key);
void create_shmid(int *shmid, const key_t key);
void attach(message **msg, const int shmid);

booth.c代码:

代码语言:javascript
运行
复制
#include "booth.h"

static char pid_char[128];
char * get_client_com_file_name(pid_t pid){
  memset(pid_char, 0, 127);
  sprintf(pid_char,"%d", pid);
  printf("pid_char: %s\n", pid_char);
  strcat(pid_char, "_com");
  return pid_char;
}

void inform_dispatcher(int dispatcher_id){
    printf("Informing: %d\n", dispatcher_id);
    kill(dispatcher_id, SIGUSR1);
}

static void get_key(key_t *key, char* file_name){
    if((*key = ftok(file_name, 'R')) == -1){
        int err = errno;
        perror("ftok");
        printf("Error number: %d\n", err);
        exit(1);
    }
}

void get_factory_key(key_t *key){
    get_key(key, "factory_com");
}

void get_client_key(key_t *key, pid_t client_pid){
    char buf[10];

    sprintf(buf, "%d", client_pid);
    get_key(key, buf);
}

void create_shmid(int *shmid, const key_t key){
    if((*shmid = shmget(key,BUFSIZE, PERM | IPC_CREAT)) == -1){
        int err = errno;
        perror("shmget");
        printf("Error number: %d\n", err);
        exit(1);
    }
}

void get_shmid(int *shmid, const key_t key){
    if((*shmid = shmget(key,BUFSIZE, PERM)) == -1){
        int err = errno;
        perror("shmget");
        printf("Error number: %d\n", err);
        exit(1);
    }
}

void attach(message **msg, const int shmid){
    *msg = (message*) shmat(shmid, (void *)0, 0);
    if (msg == (message**)(-1)){
        perror("shmat");
        exit(1);
    }
}

message message_request(pid_t pid){
    kill(SIGUSR2, pid);
    message m;
    return m;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-12 22:01:28

我运行了messeage_queue,得到了1056个字节,将近1KB。

在第22行中,您分配了INT_MAX * 1056字节=2 TB!。

message_vector是一个全局变量,在运行程序之前,内存是在BSS中分配的,这就是为什么在代码运行之前就会看到分段错误。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42193212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档