C Unix Xcode 再次出现错误
C Unix Xcode bug again
我在做一个大学项目,我们要用到Unix系统调用。
现在,我真的很难理解在我的项目中是否真的存在错误。这是因为,虽然它在终端中编译并且开始和结束时没有错误,但在 xcode 上我遇到了几个错误。
特别是,我在使用信号量时遇到错误。
我会尝试解释我收到的错误,但由于我的母语不是英语,如果我犯了一些错误,请提前原谅我。
首先,程序用fork()创建了多个child进程。它取决于有多少 clientei.txt 位于(i = 迭代器)。
我立即用信号量阻止 parent,我 运行 child 达到某个点,然后我用信号量阻止它并重新启动 parent.
此时,parent应该读取儿子发送的消息,调用函数打印log.txt中的内容并重启儿子。
然后 child 做其他事情(包括删除消息)并阻止。
parent 重新启动,并为随后的 children.
重复一切
虽然终端同步是完美的(一切都在正确的时间发生,没有错误)这 Linux 和 Mac,关于 XCode 我有几个错误:
semop: 资源暂时不可用(如果我创建了超过5个txt)
semop:文件太大(如果我创建了 2 个以上)
with 2 相反给了我两个错误:
semop 1:中断的系统调用(这在 运行ning 两个进程之后停止)
semop 3:标识符已删除(在重新启动第二个进程时)
做C的时间不多了,不知道干什么。我想首先知道我是否需要担心(所以有一个错误),或者我必须保持安静,因为它是 xcode 中的一个错误。
如果有错误,我恳请您不要要求我大量更改代码。
这主要是因为它们快要过期了,我负担不起再做一遍。
如果可以的话,我还请您尽可能清楚。我懂足够的英语,但还不够 mother-tongue,我不能总是关注 Whosebug 上的回复。
代码在这里:
https://www.dropbox.com/s/2utsb6r5d7kzzqj/xcode%2Bterminal.zip?dl=0
这个 zip 包含有这个问题的项目的一小部分。
终端版本有效。这个版本有一个makefile来简化编译。
xcode 版本不工作。它包含调试文件夹。实际上 xcode, txt 文件,它不会从根文件夹中读取代码所在的文件夹,该文件夹位于它创建编译的文件夹中。每个案例都有一个自述文件,详细说明了过程。
我尽量减少,我评论都是英文的。
我删除了不需要的代码,但我添加了包含所有使用的包含和函数的文件。
这里是代码:
main.c
key_t key, key_2;
int semid, semid_2;
union semun arg;
union semun arg_2;
struct sembuf sb_2 = {0, -1, 0};
char* nome_file;
nome_file = (char*) malloc(sizeof(char*));
int numero_clienti;
//semaphore for all the child
struct sembuf sb[numero_clienti];
int i_c;
for (i_c = 0; i_c < numero_clienti; i_c++) {
sb[i_c].sem_num = i_c;
sb[i_c].sem_op = -1;
sb[i_c].sem_flg = 0;
}
//cretion of first SEMAPHORE
{
//key creation
if ((key = ftok("cliente0.txt", 'J')) == -1)
{
perror("ftok");
exit(EXIT_FAILURE);
}
//creation of the semaphore
if ((semid = semget(key, numero_clienti, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}
//set value of all child semaphore
for (i_c = 0; i_c < numero_clienti; i_c++) {
arg.val = 0;
if (semctl(semid, i_c, SETVAL, arg) == -1)
{
perror("semctl");
exit(EXIT_FAILURE);
}
}
}
//cretion of second SEMAPHORE
{
//key creation
if ((key_2 = ftok("cliente1.txt", 'J')) == -1)
{
perror("ftok");
exit(EXIT_FAILURE);
}
//creation of the semaphore
if ((semid_2 = semget(key_2, 1, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}
//set value of parent semaphore
arg_2.val = 0;
if (semctl(semid_2, 0, SETVAL, arg_2) == -1)
{
perror("semctl");
exit(EXIT_FAILURE);
}
}
while(fd > 0 && pid > 0){
j++;
close(fd);
pid = fork();
if(pid != 0)
{
i++;
sprintf(nome_file, "./cliente%d.txt", i);
fd = open(nome_file, O_RDONLY);
}
switch(pid)
{
//error case
case -1:
{
perror("Error during fork.");
exit(EXIT_FAILURE);
break;
}
//child case
case 0:
{
puts("Child: I'm a child");
messaggio(numero_clienti, j);
puts("Child: I have to do something");
//Start parent
sb_2.sem_op = 1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop");
exit(1);
}
//, stop itself
sb[j].sem_op = -1;
if (semop(semid, &sb[j], 1) == -1)
{
perror("semop");
exit(1);
}
printf("Child: I have to do something else %d\n", getpid());
_exit(EXIT_SUCCESS);
break;
}
//parent case
default:
{
puts("Parent: I'm a parent");
//Stop itself
sb_2.sem_op = -1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop padre");
exit(1);
}
puts("Parent: now I can send the message, my child is blocked");
//restart child
sb[j].sem_op = 1;
if (semop(semid, &sb[j], 1) == -1)
{
perror("semop");
exit(1);
}
//stop itself
sb_2.sem_op = -1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop");
exit(1);
}
puts("Parent: end of while");
break;
}
}
}
puts("Parent: I can restart all my child");
for (i_c = 0; i_c < numero_clienti; i_c++) {
sb[i_c].sem_op = 1;
if (semop(semid, &sb[i_c], 1) == -1)
{
perror("semop");
exit(1);
}
}
puts("I wait the end of my child...");
while (wait(NULL) != -1);
puts("All child end");
//remove semaphore I create
if (semctl(semid, 0, IPC_RMID, arg) == -1)
{
perror("semctl");
exit(1);
}
if (semctl(semid_2, 0, IPC_RMID, arg_2) == -1)
{
perror("semctl");
exit(1);
}
puts("FINE");
return 0;
}
cliente.c
#include "cliente.h"
/**
inside this function child do some thing.
1. at this point it give control to parent after it create a message
2. at this point it remove the message
*/
void messaggio(int numero_clienti, int num_j){
key_t key, key_2;
int semid, semid_2;
struct sembuf sb[numero_clienti];
int i_c;
for (i_c = 0; i_c < numero_clienti; i_c++) {
sb[i_c].sem_num = i_c;
sb[i_c].sem_op = -1;
sb[i_c].sem_flg = 0;
}
struct sembuf sb_2 = {0, -1, 0};
if ((key = ftok("cliente0.txt", 'J')) == -1) {
perror("ftok");
exit(1);
}
if ((semid = semget(key, 1, 0)) == -1) {
perror("semget");
exit(1);
}
if ((key_2 = ftok("cliente1.txt", 'J')) == -1) {
perror("ftok");
exit(1);
}
if ((semid_2 = semget(key_2, 1, 0)) == -1) {
perror("semget");
exit(1);
}
//creation of a message
//1. Restart parent
sb_2.sem_op = 1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop");
exit(1);
}
puts("cambio sem");
//stop itself
sb[num_j].sem_op = -1;
if (semop(semid, &sb[num_j], 1) == -1)
{
perror("semop");
exit(1);
}
//here it can move again
puts("remove message");
puts("Figlio: sono tornato attivo, mio padre aspetta");
}
你第一次做
nome_file = (char*) malloc(sizeof(char*));
分配 4 或 8 个字节(取决于您编译的平台:32 位或 64 位)。
那你就做
sprintf(nome_file, "./cliente%d.txt", i);
后者写入无效内存,因为 "./cliente%d.txt"
的长度为 14+1 个字符加上来自 i
if i>9
的潜在位数或者如果 [=22] 的附加符号=].
要解决此问题,请分配所需内容:
nome_file = malloc(13 + 10 + 1 + 1); /* 13 for the filename,
10 for the digits,
1 for a potential sign,
1 the C-"strings" 0-terminator. */
这是一个非常丑陋的错误,预计将成为您代码中的主要问题。
此外 在函数 read_line()
的源代码(您链接的)中分配内存,您没有正确初始化,但稍后取决于其内容。
main.c:20
char* myb2 = (char*) malloc(sizeof(char*));
malloc()
不会初始化它分配的内存,所以要么:
char * myb2 = calloc(1, sizeof(char*));
的添加和额外调用
memset(mb2, 0, sizeof(char*));
调用 malloc()
之后。
这个bug也很讨厌。
另外^2 你应该使用 gcc 的选项构建 -std=c99 -D_XOPEN_SOURCE
.
那是因为:
您正在使用仅从 C99 提供的 C 构造。通常是 VLA,因此通过明确声明 -std=c99
告诉编译器将代码视为 C99 代码
To #define
_XOPEN_SOURCE
是由 gcc 发布的,对于一些 header 你包含在你的项目中。
另外^3 你似乎不一定计算正确的客户端(文件)数量,至少如果你的文件是按照你链接的存档分发的:
main.c:82
system("ls cliente* | wc -l");
将其更改为:
system("ls cliente*.txt | wc -l");
如果上面描述的错误应该 return 更多文件,那么实际上有以下代码也会从 i
的某个值开始失败:
main.c:176
fd = open(nome_file, O_RDONLY);
以上操作的结果未测试。使用了可能无效的 fd
并且臭名昭着的未定义行为正在接管。一切皆有可能。
最后一点:这主要是从来没有我们正在使用的工具中的错误。
我在做一个大学项目,我们要用到Unix系统调用。 现在,我真的很难理解在我的项目中是否真的存在错误。这是因为,虽然它在终端中编译并且开始和结束时没有错误,但在 xcode 上我遇到了几个错误。
特别是,我在使用信号量时遇到错误。
我会尝试解释我收到的错误,但由于我的母语不是英语,如果我犯了一些错误,请提前原谅我。
首先,程序用fork()创建了多个child进程。它取决于有多少 clientei.txt 位于(i = 迭代器)。 我立即用信号量阻止 parent,我 运行 child 达到某个点,然后我用信号量阻止它并重新启动 parent.
此时,parent应该读取儿子发送的消息,调用函数打印log.txt中的内容并重启儿子。
然后 child 做其他事情(包括删除消息)并阻止。 parent 重新启动,并为随后的 children.
重复一切虽然终端同步是完美的(一切都在正确的时间发生,没有错误)这 Linux 和 Mac,关于 XCode 我有几个错误:
semop: 资源暂时不可用(如果我创建了超过5个txt) semop:文件太大(如果我创建了 2 个以上)
with 2 相反给了我两个错误: semop 1:中断的系统调用(这在 运行ning 两个进程之后停止) semop 3:标识符已删除(在重新启动第二个进程时)
做C的时间不多了,不知道干什么。我想首先知道我是否需要担心(所以有一个错误),或者我必须保持安静,因为它是 xcode 中的一个错误。 如果有错误,我恳请您不要要求我大量更改代码。 这主要是因为它们快要过期了,我负担不起再做一遍。 如果可以的话,我还请您尽可能清楚。我懂足够的英语,但还不够 mother-tongue,我不能总是关注 Whosebug 上的回复。
代码在这里: https://www.dropbox.com/s/2utsb6r5d7kzzqj/xcode%2Bterminal.zip?dl=0 这个 zip 包含有这个问题的项目的一小部分。 终端版本有效。这个版本有一个makefile来简化编译。 xcode 版本不工作。它包含调试文件夹。实际上 xcode, txt 文件,它不会从根文件夹中读取代码所在的文件夹,该文件夹位于它创建编译的文件夹中。每个案例都有一个自述文件,详细说明了过程。
我尽量减少,我评论都是英文的。 我删除了不需要的代码,但我添加了包含所有使用的包含和函数的文件。
这里是代码:
main.c
key_t key, key_2;
int semid, semid_2;
union semun arg;
union semun arg_2;
struct sembuf sb_2 = {0, -1, 0};
char* nome_file;
nome_file = (char*) malloc(sizeof(char*));
int numero_clienti;
//semaphore for all the child
struct sembuf sb[numero_clienti];
int i_c;
for (i_c = 0; i_c < numero_clienti; i_c++) {
sb[i_c].sem_num = i_c;
sb[i_c].sem_op = -1;
sb[i_c].sem_flg = 0;
}
//cretion of first SEMAPHORE
{
//key creation
if ((key = ftok("cliente0.txt", 'J')) == -1)
{
perror("ftok");
exit(EXIT_FAILURE);
}
//creation of the semaphore
if ((semid = semget(key, numero_clienti, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}
//set value of all child semaphore
for (i_c = 0; i_c < numero_clienti; i_c++) {
arg.val = 0;
if (semctl(semid, i_c, SETVAL, arg) == -1)
{
perror("semctl");
exit(EXIT_FAILURE);
}
}
}
//cretion of second SEMAPHORE
{
//key creation
if ((key_2 = ftok("cliente1.txt", 'J')) == -1)
{
perror("ftok");
exit(EXIT_FAILURE);
}
//creation of the semaphore
if ((semid_2 = semget(key_2, 1, 0666 | IPC_CREAT | IPC_EXCL)) == -1)
{
perror("semget");
exit(EXIT_FAILURE);
}
//set value of parent semaphore
arg_2.val = 0;
if (semctl(semid_2, 0, SETVAL, arg_2) == -1)
{
perror("semctl");
exit(EXIT_FAILURE);
}
}
while(fd > 0 && pid > 0){
j++;
close(fd);
pid = fork();
if(pid != 0)
{
i++;
sprintf(nome_file, "./cliente%d.txt", i);
fd = open(nome_file, O_RDONLY);
}
switch(pid)
{
//error case
case -1:
{
perror("Error during fork.");
exit(EXIT_FAILURE);
break;
}
//child case
case 0:
{
puts("Child: I'm a child");
messaggio(numero_clienti, j);
puts("Child: I have to do something");
//Start parent
sb_2.sem_op = 1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop");
exit(1);
}
//, stop itself
sb[j].sem_op = -1;
if (semop(semid, &sb[j], 1) == -1)
{
perror("semop");
exit(1);
}
printf("Child: I have to do something else %d\n", getpid());
_exit(EXIT_SUCCESS);
break;
}
//parent case
default:
{
puts("Parent: I'm a parent");
//Stop itself
sb_2.sem_op = -1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop padre");
exit(1);
}
puts("Parent: now I can send the message, my child is blocked");
//restart child
sb[j].sem_op = 1;
if (semop(semid, &sb[j], 1) == -1)
{
perror("semop");
exit(1);
}
//stop itself
sb_2.sem_op = -1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop");
exit(1);
}
puts("Parent: end of while");
break;
}
}
}
puts("Parent: I can restart all my child");
for (i_c = 0; i_c < numero_clienti; i_c++) {
sb[i_c].sem_op = 1;
if (semop(semid, &sb[i_c], 1) == -1)
{
perror("semop");
exit(1);
}
}
puts("I wait the end of my child...");
while (wait(NULL) != -1);
puts("All child end");
//remove semaphore I create
if (semctl(semid, 0, IPC_RMID, arg) == -1)
{
perror("semctl");
exit(1);
}
if (semctl(semid_2, 0, IPC_RMID, arg_2) == -1)
{
perror("semctl");
exit(1);
}
puts("FINE");
return 0;
}
cliente.c
#include "cliente.h"
/**
inside this function child do some thing.
1. at this point it give control to parent after it create a message
2. at this point it remove the message
*/
void messaggio(int numero_clienti, int num_j){
key_t key, key_2;
int semid, semid_2;
struct sembuf sb[numero_clienti];
int i_c;
for (i_c = 0; i_c < numero_clienti; i_c++) {
sb[i_c].sem_num = i_c;
sb[i_c].sem_op = -1;
sb[i_c].sem_flg = 0;
}
struct sembuf sb_2 = {0, -1, 0};
if ((key = ftok("cliente0.txt", 'J')) == -1) {
perror("ftok");
exit(1);
}
if ((semid = semget(key, 1, 0)) == -1) {
perror("semget");
exit(1);
}
if ((key_2 = ftok("cliente1.txt", 'J')) == -1) {
perror("ftok");
exit(1);
}
if ((semid_2 = semget(key_2, 1, 0)) == -1) {
perror("semget");
exit(1);
}
//creation of a message
//1. Restart parent
sb_2.sem_op = 1;
if (semop(semid_2, &sb_2, 1) == -1)
{
perror("semop");
exit(1);
}
puts("cambio sem");
//stop itself
sb[num_j].sem_op = -1;
if (semop(semid, &sb[num_j], 1) == -1)
{
perror("semop");
exit(1);
}
//here it can move again
puts("remove message");
puts("Figlio: sono tornato attivo, mio padre aspetta");
}
你第一次做
nome_file = (char*) malloc(sizeof(char*));
分配 4 或 8 个字节(取决于您编译的平台:32 位或 64 位)。
那你就做
sprintf(nome_file, "./cliente%d.txt", i);
后者写入无效内存,因为 "./cliente%d.txt"
的长度为 14+1 个字符加上来自 i
if i>9
的潜在位数或者如果 [=22] 的附加符号=].
要解决此问题,请分配所需内容:
nome_file = malloc(13 + 10 + 1 + 1); /* 13 for the filename,
10 for the digits,
1 for a potential sign,
1 the C-"strings" 0-terminator. */
这是一个非常丑陋的错误,预计将成为您代码中的主要问题。
此外 在函数 read_line()
的源代码(您链接的)中分配内存,您没有正确初始化,但稍后取决于其内容。
main.c:20
char* myb2 = (char*) malloc(sizeof(char*));
malloc()
不会初始化它分配的内存,所以要么:
char * myb2 = calloc(1, sizeof(char*));
的添加和额外调用
memset(mb2, 0, sizeof(char*));
调用 malloc()
之后。
这个bug也很讨厌。
另外^2 你应该使用 gcc 的选项构建 -std=c99 -D_XOPEN_SOURCE
.
那是因为:
您正在使用仅从 C99 提供的 C 构造。通常是 VLA,因此通过明确声明
-std=c99
告诉编译器将代码视为 C99 代码
To
#define
_XOPEN_SOURCE
是由 gcc 发布的,对于一些 header 你包含在你的项目中。
另外^3 你似乎不一定计算正确的客户端(文件)数量,至少如果你的文件是按照你链接的存档分发的:
main.c:82
system("ls cliente* | wc -l");
将其更改为:
system("ls cliente*.txt | wc -l");
如果上面描述的错误应该 return 更多文件,那么实际上有以下代码也会从 i
的某个值开始失败:
main.c:176
fd = open(nome_file, O_RDONLY);
以上操作的结果未测试。使用了可能无效的 fd
并且臭名昭着的未定义行为正在接管。一切皆有可能。
最后一点:这主要是从来没有我们正在使用的工具中的错误。