У вас есть неограниченное переполнение буфера, потому что вы не завершаете строку нулем. У вас есть:
char packet[PLENGHT];
for(int i = 0; i < PLENGHT; i++) packet[i] = 'a';
…lots of lines…
strcpy(shmem_char, packet);
Копирование не-строки с strcpy()
не очень хорошая идея - у вас переполнение буфера. Я добавил:
packet[PLENGHT - 1] = '\0';
и все, казалось, работало.
Я добавил некоторую информацию о диагностике c и получил:
data written, iteration number :17499
data read, iteration number: 17499 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
Затем программы зависли - Мне пришлось их прервать.
Обратите внимание, что PLENGTH
было бы более нормальным написанием для длины.
Исправленный код test1.c
Я уменьшил число итераций до 25 (с 17500). Я исправил различные вещи и решил использовать свой собственный код сообщения об ошибках, который доступен в моем репозитории SOQ (вопросы о переполнении стека) на GitHub в виде файлов stderr.c
и stderr.h
в * 1025 Подкаталог * src / libsoq . Мне нужно было знать, какая программа генерирует ошибку; Я получил информацию (это было test1
), используя эти функции. Я не тратил время на модернизацию кода в test2.c
. Я добавил дополнительные pthread_cond_signal()
после основного l oop в test1.c
; теперь ребенок выходит, поэтому родитель выходит - и все в порядке. Все вызовы pthread_*
проверены на ошибки. Код изменяет сообщение до его отправки, чтобы вы могли определить, правильно ли ребенок забирает сообщение. Сообщение печатается до его отправки и после прочтения.
Основное исправление ошибки - добавление;
packet[PLENGTH - 1] = '\0';
Это гарантирует, что пакет содержит строку, а не только полный буфер байтов.
#include "stderr.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
//#define PNUM 17500
#define PNUM 25
#define PLENGTH 60
#define MAXLINE 4096
int main(int argc, char **argv)
{
if (argc > 0)
err_setarg0(argv[0]);
/* creating new mutex inside shared memory area */
void *shmem_mu_ptr; /* pointer to mutex shared memory */
pthread_mutex_t *mu; /* pointer to mutex */
int shmem_mu_id; /* shared memory mutex id */
int mu_err;
size_t size = sizeof(pthread_mutex_t); /* shared m. mutex size (size was already declared) */
char packet[PLENGTH];
for (int i = 0; i < PLENGTH; i++)
packet[i] = 'a';
packet[PLENGTH - 1] = '\0';
/* getting shared m. id for mutex*/
if ((shmem_mu_id = shmget((key_t)1111, size, 0666 | IPC_CREAT)) == -1)
err_syserr("shared memory error ");
/* getting shared m. pointer for mutex */
if ((shmem_mu_ptr = shmat(shmem_mu_id, 0, 0)) == (void *)-1)
err_syserr("shmat error: ");
/* make mu, that expects a memory area made like pthread_mutex_t , to point the shared memory. */
mu = (pthread_mutex_t *)shmem_mu_ptr;
/* initialize the attribute to prepare mutex to be placed in shared memory */
int rc;
pthread_mutexattr_t attr;
if ((rc = pthread_mutexattr_init(&attr)) != 0)
err_syserror(rc, "pthread_mutexattr_init: ");
if ((rc = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) != 0)
err_syserror(rc, "pthread_mutexattr_setpshared: ");
/* initialize mutex */
if ((rc = pthread_mutex_init(mu, &attr)) != 0)
err_syserror(rc, "pthread_mutex_init: ");
if ((rc = pthread_mutexattr_destroy(&attr)) != 0)
err_syserror(rc, "pthread_mutexattr_destroy: ");
/* creating new condition variable inside shared memory area */
void *shmem_cond_ptr; /* pointer to cond shared memory */
int shmem_cond_id; /* shared memory cond id */
pthread_cond_t *cond;
size = sizeof(pthread_cond_t); /* shared m. cond size (size was already declared) */
/* getting shared m. id for cond*/
if ((shmem_cond_id = shmget((key_t)2222, size, 0666 | IPC_CREAT)) == -1)
err_syserr("shared memory error ");
/* getting shared m. pointer for cond */
if ((shmem_cond_ptr = shmat(shmem_cond_id, 0, 0)) == (void *)-1)
err_syserr("shmat error: ");
/* make cond, that expects a memory area made like pthread_cond_t , to point the shared memory. */
cond = (pthread_cond_t *)shmem_cond_ptr;
/* * initialize the attribute to prepare cond to be placed in shared memory */
pthread_condattr_t attrcond;
if ((rc = pthread_condattr_init(&attrcond)) != 0)
err_syserror(rc, "pthread_condattr_init: ");
if ((rc = pthread_condattr_setpshared(&attrcond, PTHREAD_PROCESS_SHARED)) != 0)
err_syserror(rc, "pthread_condattr_setpshared: ");
/* Initialize condition. */
if ((rc = pthread_cond_init(cond, &attrcond)) != 0)
err_syserror(rc, "pthread_cond_init: ");
if ((rc = pthread_condattr_destroy(&attrcond)) != 0)
err_syserror(rc, "pthread_condattr_destroy: ");
/* Clean up. */
//pthread_condattr_destroy(&attrcond);
/* creating new shared memory area to share only PLENGTH (60) byte at time */
void *shmem_ptr60;
int shmem60;
char *shmem_char;
size = sizeof(char) * PLENGTH; /* shared m. data size (size was already declared) */
/* getting shared m. id */
if ((shmem60 = shmget(3333, size, 0666 | IPC_CREAT)) == -1)
err_syserr("shared memory error ");
/* getting shared m. pointer */
if ((shmem_ptr60 = shmat(shmem60, 0, 0)) == (void *)-1)
err_syserr("shmat error: ");
shmem_char = shmem_ptr60;
/* locking mutex before creating new process to avoid child reading void memory area */
if ((mu_err = pthread_mutex_lock(mu)) != 0)
err_syserror(mu_err, "lock mutex error: ");
/* calling child */
pid_t pid;
//if ((pid = vfork()) == -1)
if ((pid = fork()) == -1)
err_syserr("fork error: ");
else if (pid == 0)
{
if (execl("./test2", "test2", (void *)0) == -1)
err_syserr("exec error: ");
exit(0);
}
//else if (pid == -1)
//err_syserr("fork error: ");
printf("Child forked OK\n");
/* copying data inside shared memory */
for (int i = 0; i < PNUM; i++)
{
packet[i % (PLENGTH - 1)]++;
strcpy(shmem_char, packet);
printf("data written, iteration number: %d [%s]\n", i, packet);
if ((mu_err = pthread_cond_signal(cond)) != 0)
err_syserror(mu_err, "pthread_cond_signal: ");
if ((mu_err = pthread_cond_wait(cond, mu)) != 0)
err_syserror(mu_err, "pthread_cond_wait: ");
}
if ((mu_err = pthread_cond_signal(cond)) != 0)
err_syserror(mu_err, "pthread_cond_signal: ");
if ((mu_err = pthread_mutex_unlock(mu)) != 0)
err_syserror(mu_err, "pthread_mutex_unlock: ");
waitpid(pid, NULL, 0);
if (shmctl(shmem_mu_id, IPC_RMID, 0) < 0)
err_syserr("shmctl error: ");
if (shmctl(shmem_cond_id, IPC_RMID, 0) < 0)
err_syserr("shmctl error: ");
if (shmctl(shmem60, IPC_RMID, 0) < 0)
err_syserr("shmctl error: ");
return 0;
}
Пересмотренный код test2.c
Как правило, это значительно менее сильно отредактировано.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
//#define PNUM 17500
#define PNUM 25
#define MAXLINE 4096
#define PLENGTH 60
void err_sys(const char *fmt, ...);
void err_exit(int error, const char *fmt, ...);
static void err_doit(int errnoflag, int error, const char *fmt, va_list ap);
int main(void)
{
char packets[PNUM][PLENGTH];
/* -----recovering mutex inside shared memory */
pthread_mutex_t *mu;
int shmem_mu_id;
void *shmem_mu_ptr;
int mu_err;
/* getting shared m. id for data*/
if ((shmem_mu_id = shmget((key_t)1111, 0, 0666 | IPC_CREAT)) == -1)
err_sys("shared memory error ");
/* getting shared m. pointer for data */
if ((shmem_mu_ptr = shmat(shmem_mu_id, 0, 0)) == (void *)-1)
err_sys("shmat error");
/* make mu, that expects a memory area made like pthread_mutex_t *, to point the shared memory. */
mu = (pthread_mutex_t *)shmem_mu_ptr;
printf("mutex recovered\n");
/* -----recovering condition variable inside shared memory */
void *shmem_cond_ptr; /* pointer to cond shared memory */
int shmem_cond_id; /* shared memory cond id */
pthread_cond_t *cond;
/* getting shared m. id for cond*/
if ((shmem_cond_id = shmget((key_t)2222, 0, 0666 | IPC_CREAT)) == -1)
err_sys("shared memory error ");
/* getting shared m. pointer for cond */
if ((shmem_cond_ptr = shmat(shmem_cond_id, 0, 0)) == (void *)-1)
err_sys("shmat error");
/* make cond, that expects a memory area made like pthread_cond_t , to point the shared memory. */
cond = (pthread_cond_t *)shmem_cond_ptr;
printf("condition recovered\n");
/* recovering shared memory read with data */
int shmem;
char *shmem_ptr;
if ((shmem = shmget(3333, 0, 0666)) == -1)
err_sys("shared memory error ");
if ((shmem_ptr = shmat(shmem, 0, 0)) == (void *)-1)
err_sys("shmat error child");
printf("data memory recovered\n");
if ((mu_err = pthread_mutex_lock(mu)) != 0)
err_exit(mu_err, "lock mutex error");
/* try to read data inside shared memory */
for (int i = 0; i < PNUM; i++)
{
strcpy(packets[i], shmem_ptr);
printf("data read, iteration number: %d [%s]\n", i, packets[i]);
if ((mu_err = pthread_cond_signal(cond)) != 0)
err_exit(mu_err, "cond signal error: ");
if ((mu_err = pthread_cond_wait(cond, mu)) != 0)
err_exit(mu_err, "cond wait error");
}
if ((mu_err = pthread_mutex_unlock(mu)) != 0)
err_exit(mu_err, "mutex unlock error");
return 0;
}
/* from apue to print errors*/
void err_sys(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
exit(1);
}
void err_exit(int error, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, error, fmt, ap);
va_end(ap);
exit(1);
}
static void err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
char buf[MAXLINE];
vsnprintf(buf, MAXLINE - 1, fmt, ap);
if (errnoflag)
snprintf(buf + strlen(buf), MAXLINE - strlen(buf) - 1, ": %s",
strerror(error));
strcat(buf, "\n");
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(NULL); /* flushes all stdio output streams */
}
Пример вывода
$ ./test1
Child forked OK
data written, iteration number: 0 [baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
mutex recovered
condition recovered
data memory recovered
data read, iteration number: 0 [baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 1 [bbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 1 [bbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 2 [bbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 2 [bbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 3 [bbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 3 [bbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 4 [bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 4 [bbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 5 [bbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 5 [bbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 6 [bbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 6 [bbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 7 [bbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 7 [bbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 8 [bbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 8 [bbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 9 [bbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 9 [bbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 10 [bbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 10 [bbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 11 [bbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 11 [bbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 12 [bbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 12 [bbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 13 [bbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 13 [bbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 14 [bbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 14 [bbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 15 [bbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 15 [bbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 16 [bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 16 [bbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 17 [bbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 17 [bbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 18 [bbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 18 [bbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 19 [bbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 19 [bbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 20 [bbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 20 [bbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 21 [bbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 21 [bbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 22 [bbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 22 [bbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 23 [bbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 23 [bbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data written, iteration number: 24 [bbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
data read, iteration number: 24 [bbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]
$
Тестовая среда
Я использую MacBook Pro с MacOS Catalina 10.15.3 и использую G CC 9.2.0 (который я сам скомпилировал) и Xcode 11.3.1 для всего, что формально не является частью G CC.
Любопытное наблюдение: у меня, похоже, нет справочной страницы для pthread_mutexattr_setpshared()
или pthread_condattr_setpshared()
, но обе функции обнаруживаются при компоновке (и компиляции) и, похоже, работают нормально.