我正在编写一个程序来学习和探索linux的IPC机制,我的目标之一是在我的进程之间创建一个共享内存,它存储了我需要的所有东西(POSIX信号量,结构和其他变量) . 我用valgrind运行我的应用程序,它工作正常但是当我在valgrind之外运行时,我得到了一个分段错误 . 但是当在valgrind中时,一切都正常运行并且内存按预期写入/读取,否则它会崩溃,因此很难调试它 .
这是初始化过程的代码:
#include <iostream>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <ctype.h>
#include <fcntl.h> /* O_CREAT, O_EXEC */
#include <pthread.h>
#include "myheader.h"
#define PERMS 0666
#define logfile "./logfile.log"
void perror_exit(char *message);
bool init_arguments(int argc, char *argv[], int *typeS_spots, int *typeM_spots, int *typeL_spots, int *typeS_cost, int *typeM_cost, int *typeL_cost, int *time_unit);
bool init_shm(int typeS_spots, int typeM_spots, int typeL_spots, int typeS_cost, int typeM_cost, int typeL_cost, int time_unit);
bool shm_upgrade(int shmid, int size);
int count_args(char *arguments);
bool increase_shm(shm_ledger **led, void **current_shm, int old_size, int new_size);
bool copy_shm();
int main(int argc, char *argv[])
{
if (argc < 3)
{
perror_exit("Usage: ./myport -l <filename>\n");
return (-1);
}
int typeS_spots=0, typeM_spots=0, typeL_spots=0, typeS_cost=0, typeM_cost=0, typeL_cost=0, time_unit=0, pid=0, /* i=0 ,*/ status=0, num_of_arguments=0;
bool everything_ok = false;
int shm_portid=0,current_shm_ledgerid=0;
shm_port *port = NULL;
everything_ok = init_arguments(argc, argv, &typeS_spots, &typeM_spots, &typeL_spots, &typeS_cost, &typeM_cost, &typeL_cost, &time_unit);
if (!everything_ok)
{
perror_exit("INIT FAILED!, exiting");
}
// FILE *fd = fopen("logfile.log", "wa+");
printf("%d %d %d %d %d %d %d\n", typeS_spots, typeM_spots, typeL_spots, typeS_cost, typeM_cost, typeL_cost, time_unit);
const int shmsize = sizeof(shm_port)+(vessel_name+logfile_len+1)*sizeof(char);
shm_portid = shmget(IPC_PRIVATE,shmsize,IPC_CREAT | PERMS);
// printf("shm_port size is: %d, shm_port+the strings size is: %d\n", sizeof(shm_port), shmsize);
void *port_shm = shmat(shm_portid,0,0);
port = (shm_port *)port_shm;
/*------- Initialize semaphores -------*/
sem_init(&port->Sspots,0,typeS_spots);
fprintf(stderr,"port->Sspots errno is: %s\n",strerror(errno));
sem_init(&port->Mspots,0,typeM_spots);
fprintf(stderr,"port->Mspots errno is: %s\n",strerror(errno));
sem_init(&port->Lspots,0,typeL_spots);
fprintf(stderr,"port->Lspots errno is: %s\n",strerror(errno));
sem_init(&port->maneuver,0,1);
fprintf(stderr,"port->maneuver errno is: %s\n",strerror(errno));
sem_init(&port->cost_ask_sem,0,1);
fprintf(stderr,"port->cost_ask_sem errno is: %s\n",strerror(errno));
sem_init(&port->vessel_info_sem,0,1);
fprintf(stderr,"port->vessel_info_sem errno is: %s\n",strerror(errno));
/*------- Initialize strings -------*/
// printf("I get here: %s %d\n", __FILE__, __LINE__);
port->v_info.ves_name = new char[vessel_name];
memset(port->v_info.ves_name, '\0', vessel_name);
sprintf(port->v_info.ves_name, "%s", "koula");
printf("ves_name is: -->%s<--\n", port->v_info.ves_name);
printf("I get here: %s %d\n", __FILE__, __LINE__);
port->v_info.type = new char[1];
memset(port->v_info.type, '\0', 1);
port->logfile_path = new char[strlen(logfile)+1];
memset(port->logfile_path, '\0', strlen(logfile));
sprintf(port->logfile_path, "%s", logfile);
printf("logfile path is: %s\n", port->logfile_path);
/*------- Initialize arrays -------*/
port->cost[0] = typeS_cost;
port->cost[1] = typeM_cost;
port->cost[2] = typeL_cost;
port->cost[3] = time_unit;
int ledger_size = sizeof(shm_ledger)+sizeof(ledger_node);
current_shm_ledgerid = shmget(IPC_PRIVATE,ledger_size,IPC_CREAT | PERMS);
// printf(" sizeof(port): %d , int[4], %d, %d shmsize = %d\n", sizeof(shm_port), sizeof(int[4]), sizeof(char**), shmsize);
void *current_ledger_shm = shmat(current_shm_ledgerid,0,0);
shm_ledger *curr_led = NULL;
curr_led = (shm_ledger *)current_ledger_shm;
curr_led->nodes = new ledger_node[1];
curr_led->nodes[0].name = new char[vessel_name];
sprintf(curr_led->nodes[0].name,"kitsos");
printf("ledger has a ship named %s\n", curr_led->nodes[0].name);
int new_size = ledger_size + sizeof(ledger_node);
increase_shm(&curr_led, ¤t_ledger_shm, ledger_size, new_size);
printf("I get here: %s %d\n", __FILE__, __LINE__);
curr_led->nodes[1].name = new char[vessel_name];
sprintf(curr_led->nodes[1].name,"mitsos");
printf("ledger has a ship named %s AND A SHIP NAMED %s\n", curr_led->nodes[0].name, curr_led->nodes[1].name);
// pid = fork();
// if (pid == 0)
// {
// status = execl("./port_master", NULL);
// fprintf(stderr,"EXEC for port_master failed, errno is: %s\n",strerror(errno));
// exit(-1);
// }
// pid = fork();
// if (pid == 0)
// {
// status = execl("./monitor", NULL);
// fprintf(stderr,"EXEC for monitor failed, errno is: %s\n",strerror(errno));
// exit(-1);
// }
char *yrn = new char[2];
size_t nread = 0;
char *arguments = new char[50];
char *t= new char[30];
char *u= new char[30];
char *p= new char[30];
char *m= new char[30];
char *s= new char[30];
while (true)
{
printf("Do you want to add another vessel? [y]/[n]\n");
getline(&yrn, &nread, stdin);
if (strcmp(yrn,"y\n")==0)
{
memset(arguments, '\0',50);
memset(t, '\0',30);
memset(u, '\0',30);
memset(p, '\0',30);
memset(m, '\0',30);
memset(s, '\0',30);
printf("ok, give me the arguments ('<type> <postype>* <parkperiod> <mantime> (* is optional)')\n");
getline(&arguments, &nread, stdin);
arguments[nread-1]='\0'; // skip the '\n'
num_of_arguments = count_args(arguments);
printf("num of args is: %d\n", num_of_arguments);
if ((num_of_arguments<3) || (num_of_arguments>4))
{
perror("Wrong number of arguments for a Vessel\n");
}else if(num_of_arguments ==3)
{
sprintf(t, "%s",strtok(arguments, " "));
// sprintf(u, "%s",strtok(NULL, " "));
sprintf(p, "%s",strtok(NULL, " "));
sprintf(m, "%s",strtok(NULL, " "));
sprintf(s, "%d",shm_portid);
printf("arguments for execl vessel are: t=%s p=%s m=%s s=%s\n", t, p, m, s);
pid = fork();
if (pid == 0)
{
status = execl("./vessel", "-t", t, "-p", p, "-m", m, "-s", s, NULL);
fprintf(stderr,"EXEC for failed, errno is: %s\n",strerror(errno));
exit(-1);
}
}else if (num_of_arguments == 4){
sprintf(t, "%s",strtok(arguments, " "));
sprintf(u, "%s",strtok(NULL, " "));
sprintf(p, "%s",strtok(NULL, " "));
sprintf(m, "%s",strtok(NULL, " "));
sprintf(s, "%d",shm_portid);
printf("arguments for execl vessel are: t=%s u=%s p=%s m=%s s=%s\n", t, u, p, m, s);
pid = fork();
if (pid == 0)
{
status = execl("./vessel", "-t", t, "-u", u, "-p", p, "-m", m, "-s", s, NULL);
fprintf(stderr,"EXEC for failed, errno is: %s\n",strerror(errno));
exit(-1);
}
}
}else{
break;
}
}
sem_close(&port->Sspots);
sem_close(&port->Mspots);
sem_close(&port->Lspots);
shmdt(port_shm);
}
bool init_arguments(int argc, char *argv[], int *typeS_spots, int *typeM_spots, int *typeL_spots, int *typeS_cost, int *typeM_cost, int *typeL_cost, int *time_unit)
{
int pos = 0, i = 0;
char *filename = NULL;
char *line = NULL;
size_t len = 0;
size_t nread = 0;
char *field1 = NULL;
field1 = new char[25];
memset(field1, '\0', 25);
FILE *fp = NULL;
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-l") == 0) // -f flag stands for input_filename
{
pos = i + 1;
filename = new char[strlen(argv[pos]) + 1];
memset(filename, '\0', strlen(argv[pos]) + 1);
strncpy(filename, argv[i + 1], strlen(argv[i + 1])); // +1 to get "\n" too, without +1 seg fault appears
printf("MYPORT, config filename is: %d\n",filename);
}
}
if (filename != NULL)
{
fp = fopen(filename, "r");
while ((nread = getline(&line, &len, fp)) != -1)
{
if (strstr(line, "Types:"))
{
for (i = 0; i < 3; i++)
{
nread = getline(&line, &len, fp);
field1 = strtok(line, "\t");
if (strstr(field1, "S"))
*typeS_spots = atoi(strtok(NULL, "\t"));
if (strstr(field1, "M"))
*typeM_spots = atoi(strtok(NULL, "\t"));
if (strstr(field1, "L"))
*typeL_spots = atoi(strtok(NULL, "\t"));
memset(field1, '\0', 25);
}
}
else if (strstr(line, "Cost:"))
{
for (i = 0; i < 3; i++)
{
nread = getline(&line, &len, fp);
field1 = strtok(line, "\t");
if (strstr(field1, "S"))
*typeS_cost = atoi(strtok(NULL, "\t"));
if (strstr(field1, "M"))
*typeM_cost = atoi(strtok(NULL, "\t"));
if (strstr(field1, "L"))
*typeL_cost = atoi(strtok(NULL, "\t"));
memset(field1, '\0', 25);
}
}
else
{
nread = getline(&line, &len, fp);
*time_unit = atoi(line);
}
}
free(line);
return true;
}
else
{
return false;
}
}
void perror_exit(char *message)
{
perror(message);
exit(-1);
}
bool increase_shm(shm_ledger **led, void **current_shm, int old_size, int new_size){
void *new_shm_ledger = NULL;
int id = shmget(IPC_PRIVATE, new_size,IPC_CREAT | PERMS);
new_shm_ledger = shmat(id, 0, 0);
*led = (shm_ledger *)new_shm_ledger;
(*led)->nodes = new ledger_node[new_size/sizeof(ledger_node)];
memmove(*led, *current_shm, old_size);
shmdt(*current_shm);
*current_shm = new_shm_ledger;
}
int count_args(char *arguments){
int num_of_args = 0;
char *temp = new char[strlen(arguments)+1];
memset(temp, '\0',strlen(arguments));
memcpy(temp,arguments, strlen(arguments));
if (strtok(temp, " ")!=NULL){
num_of_args++;
while(strtok(NULL, " ")!=NULL){
num_of_args++;
}
return num_of_args;
}else{
return 0;
}
}
这是正在产卵的船只:
#include <iostream>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <ctype.h>
#include <fcntl.h> /* O_CREAT, O_EXEC */
#include <pthread.h>
#include "myheader.h"
const char symbols[] = "ABCDEFHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
void perror_exit(char *message);
bool init(int argc, char * argv[], char **type, char **postype, int *parkperiod, int *mantime, int *shmid);
char *create_name(void);
int main (int argc , char* argv[]){
int parkperiod=0,mantime=0,shmid=0,random=0,status=0;
char *postype = NULL, *type = NULL;
bool everything_ok = false;
shm_port *port = NULL;
srand(time(NULL));
if(argc<8)
{
perror_exit("Usage: ./vessel -t <type> -u* <postype> -p <parkperiod> -m <mantime> -s <shmid> (* is optional)\n");
return(-1);
}
everything_ok = init(argc, argv, &type, &postype, &parkperiod, &mantime , &shmid);
if (!everything_ok)
{
perror_exit("INIT FAILED!, exiting");
}
printf("Vessel arguments, type: %s, postype: %s, parkperiod: %d, mantime: %d, shmid: %d \n", type, postype, parkperiod, mantime, shmid);
port = (shm_port *)shmat(shmid,NULL,NULL);
fprintf(stderr,"shmat errno is: %s\n",strerror(errno));
/* --------- POC CODE ---------*/
// sem_trywait(&port->Sspots);
// fprintf(stderr,"port->Sspots sem_trywait errno is: %s\n",strerror(errno));
// while(true){
// printf("vessel hehe\n");
// sleep(4);
// sem_trywait(&port->Sspots);
// if(errno==EAGAIN)printf("oops");
// fprintf(stderr,"port->Sspots sem_trywait errno is: %s\n",strerror(errno));
// }
/* --------- END OF POC CODE ---------*/
sem_wait(&port->maneuver); // wait for the port to empty from maneuvering vessels
printf("ekana down\n");
// down (spot)
// down( bainw sto limani )
printf("vessel name was: %s",port->v_info.ves_name);
char *name = create_name();
status = sprintf(port->v_info.ves_name, "%s", name);
delete name;
printf("vessel name is: %s",port->v_info.ves_name);
if (status<0){
fprintf(stderr,"%s %d errno is: %s\n", __FILE__, __LINE__, strerror(errno));
}
printf("This is the VESSEL in line %d at %s\n", __LINE__, __FILE__);
printf("port->v_info.ves_name %s\n", port->v_info.ves_name);
printf("VESSEL %d egrapsa sto port->v_info\n", __LINE__);
printf("strlen(type)= %ld\n", strlen(type));
strcpy(port->v_info.type,type);
port->v_info.in_out = true;
port->v_info.mantime = mantime;
// shmid->enhmerwsh oti bainw
sleep(mantime); // manuver
// up( bhka sto limani )
// sem_post(&port->maneuver);
random = rand() % parkperiod + 1;
sleep(parkperiod-random);
// ask for cost
sleep(random);
// down( thelw na fugw )
// shmid->tapame
// up( efuga)
}
bool init(int argc, char * argv[], char **type, char **postype, int *parkperiod, int *mantime, int *shmid){
int pos=0,i=0;
char *field1 = NULL;
field1 = new char[25];
memset(field1, '\0', 25);
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-t") == 0) // -f flag stands for input_filename
{
pos = i + 1;
*type = new char[strlen(argv[pos]) + 1];
memset(*type, '\0', strlen(argv[pos]) + 1);
strncpy(*type, argv[i + 1], strlen(argv[i + 1])); // +1 to get "\n" too, without +1 seg fault appears
std::cout << "VESSEL: type = " << *type << std::endl;
}
}
if (*type==NULL){
*type = new char[1];
sprintf(*type, "S");
}
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-u") == 0) // -f flag stands for input_filename
{
pos = i + 1;
*postype = new char[strlen(argv[pos]) + 1];
memset(*postype, '\0', strlen(argv[pos]) + 1);
strncpy(*postype, argv[i + 1], strlen(argv[i + 1])); // +1 to get "\n" too, without +1 seg fault appears
std::cout << "VESSEL: postype = " << *postype << std::endl;
}
}
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-p") == 0) // -f flag stands for input_filename
{
pos = i + 1;
*parkperiod = atoi(argv[pos]);
std::cout << "VESSEL: parkperiod = " << *parkperiod << std::endl;
}
}
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-m") == 0) // -f flag stands for input_filename
{
pos = i + 1;
*mantime = atoi(argv[pos]);
std::cout << "VESSEL: mantime = " << *mantime << std::endl;
}
}
for (i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-s") == 0) // -f flag stands for input_filename
{
pos = i + 1;
*shmid = atoi(argv[pos]);
std::cout << "VESSEL: shmid = " << *shmid << std::endl;
}
}
return true;
}
void perror_exit(char *message){
perror(message);
exit(-1);
}
char *create_name(void){
char *new_name = new char[vessel_name];
memset(new_name, '\0',vessel_name);
srand(time(NULL));
for (size_t i = 0; i < vessel_name; i++)
{
char c = symbols[rand() % sizeof(symbols)-1];
if (c != '\0') {
new_name[i] = c;
}
}
printf("NEW NAME IS: %s\n", new_name);
return new_name;
}
这些是我在myheader.h中的结构,我在上述两个文件中都包含这些结构:
#define vessel_name 15
#define logfile_len 50
typedef struct
{
char *ves_name;
char *type;
int mantime;
bool in_out;
} vessel_info;
typedef struct
{
int cost[4];
int cost_ask[2];
int cost_answer;
int ledger_shid;
char *logfile_path;
vessel_info v_info;
sem_t Sspots;
sem_t Mspots;
sem_t Lspots;
sem_t maneuver;
sem_t cost_ask_sem;
sem_t vessel_info_sem; // ensure that only one vessel writes at a time, port_master will up this when he reads and writes to ledger.
sem_t ledger; // use only to ensure that we are not reading when some1 writes.
} shm_port;
typedef struct
{
char *name;
sem_t get_in;
} ledger_node;
typedef struct
{
ledger_node *nodes;
} shm_ledger;
我用g编译它,文件是.cpp,使用new和delete而不是malloc和free不是我的问题