unix programming(memory problem i think)

In my program, the parent create processes and the child compute the sum
The problem is the parent code
so for example if going to computer 1 2 3 4 5
it going to add 1 and 2 first and then 3 and 4 and then 5 and 0(created)
There have two for loops, when it finish the inner for loop once the output is alright, but it goes into twice time the output go weird.
also it works fine with argument less than 5(1 2 3 4)
Parent code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
int main (int argc, char *argv[]) {
int pid, i, n, total, x, y, index, numOfArgument, num;
char *procpath = "/home/students/fc15105/fc1510513/slave";
char *procname = "slave";
if (argc > 9) {
printf("too many arguments\n");
exit(0);
}
numOfArgument = argc / 2;
if (argc % 2 == 0) {
        argv[argc] = "0";
}
// the outter loop tell how many time have to go
for (index = 1, i = 1; index <= argc / 2; index++) {
        x = 1; y = 2; n = 0;
        // the inner loop create the childs
        for (i; i <= numOfArgument; i++, x+=2, y+=2, n++) {
                pid = fork(); // create
                if (pid == 0) {
                // each child put argument 1, 2 and then increase by 2
                execl(procpath, procname, argv[x], argv[y], 0);
                perror("execl failed to run slave program");
                exit(1);
        }
        else if (pid > 0) {
                wait(&total); // get the sum
                num = WEXITSTATUS(total);
                printf("print index of n is %d\n", n+1);
                sprintf(argv[n+1], "%i", num); // store the sum in the first argument first
                printf("This child PID is %d and total of this child sum is %s\n", pid, argv[n+1]);
                printf("MASTER: first arguement = %s, second arguement = %s, third Arg = %s\n", argv[1], argv[2], argv[3]);
        }
        else {
                printf("call to fork failed, no child\n");
                exit(-1);
        }
}
i = 1;
if (numOfArgument % 2 != 0) { // check if argument is odd add zero after. after the inner loop
        argv[numOfArgument+1] = "0";
}
numOfArgument--;
}
}


child code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
int main (int argc, char *argv[])
{
int total = 0;
printf("Slave %s %s\n", argv[1], argv[2]);
total = atoi(argv[1]) + atoi(argv[2]);
//printf("I'm the slave and printing out the command line arguments of my master\n");
//printf("SLAVE: first argument = %s, second argument = %s\n", argv[1], argv[2]);
printf("total is %d\n", total);

exit(total);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Slave 1 2
total is 3
print index of n is 1
This child PID is 7166 and total of this child sum is 3
MASTER: first arguement = 3, second arguement = 2, third Arg = 3
Slave 3 4
total is 7
print index of n is 2
This child PID is 7167 and total of this child sum is 7
MASTER: first arguement = 3, second arguement = 7, third Arg = 3
Slave 5 0
total is 5
print index of n is 3
This child PID is 7168 and total of this child sum is 5
MASTER: first arguement = 3, second arguement = 7, third Arg = 5 // end of first inner loop
Slave 3 7
total is 10
print index of n is 1
This child PID is 7169 and total of this child sum is 10
MASTER: first arguement = 10, second arguement = , third Arg = 5 (the second one is miss, i have no idea)
Slave 5 0
total is 5
print index of n is 2
This child PID is 7170 and total of this child sum is 5
MASTER: first arguement = 105, second arguement = 5, third Arg = 5 (and later is became 105, it should be 10, but dont know how is it got 105)
Slave 105 5
total is 110
print index of n is 1
This child PID is 7171 and total of this child sum is 110
MASTER: first arguement = 110, second arguement = 0, third Arg = 5

Last edited on
Please indent your code
argv[argc] = "0"; is out of bounds
Your indentation doesn't make your code easy to follow.

Should you be writing into argv?
argv is perfectly writeable and argv[argc] = "0"; is not out of bounds (the size of argv is argc+1), that's not the problem here, per se, the problem is that the arrays pointed to by the pointers in argv are not big enough to fit the results of your additions:

When you added 3 and 7, you got 10 from the child, and you executed this line:
 
sprintf(argv[n+1], "%i", num); // store the sum in the first argument 


your n was 0, so you wrote the three bytes '1', '0', and '\0' into the memory pointed to by argv[1]

But your program was called with argv[1] = "1", with only two bytes to spare, so the last null was written who knows where.

It appears that the C runtime that called your main(), set the pointers stored in argv pointing at subsequent locations of the same array, so that '\0' actually overwrote the character in argv[2]. On the next loop, you wrote "5" into argv[2], which overwrote that null with the five. So now you have:

av[1]  av[2]
 |       | 
 v       v
'1' '0' '5' '\0'


That's why when you printed argv[1] as a string, you got 105.

PS: as gcc rightfully complained, your execl() call is wrong: the last argument must be (char*)0, not just 0.
Last edited on
> (the size of argv is argc+1)
... ¿a sentinel? ¿what's the point of argc then?
what's the point of argc then?

For convenience, I guess: the sentinel is there so that argv can be passed into another execv() (according to the original man page), and the count must be there so that you don't have to loop through argv yourself. After all, in practice, everyone is using argc.
Last edited on
Thank You guys
Learn one more thing hehe
Topic archived. No new replies allowed.