tags:

views:

80

answers:

3

I am calling a function which will branch and execute the code of another process for me. There are multiple processes, labeled B, C, and D. I have almost identical code for creating the different processes. For some bizarre reason that I can't uncover, one of the process creation functions causes a segmentation fault. They look identical to me. Any chance someone could weigh in, maybe give me some insight into what the issue is?

void spawn_process_b(int fileID[]){
    int pid;
    char * argv[2];

    sprintf(argv[0], "%d", fileID[0]);
    sprintf(argv[1], "%d", fileID[1]);

    pid = fork();

    if (pid == 0)
    {
       execv("PipeW1", argv);
    }
}

void spawn_process_c(int fileID[]){
    int pid;
    char * argv[2];

    sprintf(argv[0], "%d", fileID[0]);
    sprintf(argv[1], "%d", fileID[1]);

    pid = fork();

    if (pid == 0)
    {
       execv("PipeW2", argv);
    }
}

Through putting in breakpoints with cout << "bp1" << endl; and so on, I've discovered that spawn_process_b will execute just fine. spawn_process_c will enter, but get a segfault at the first sprintf instruction. Anyone have any ideas? Originally the spawn_process_b was giving me troubles, and...my hand to God...I didn't change a thing, and it started working. I'm almost wondering if this is something that could be dependent on the environment?

+7  A: 

argv[0] is an undefined pointer to no allocated storage when you sprintf into it.

When it worked at all, it was by accident, with the memory you scribbled on just happening to be in your process space.

The auto declaration of argv you make allocated space for two char * pointers. The pointers are likely filled with junk (that is, they point to random locations) and there is no space allocated to store characters in them.

You need something like

char *argv[3];
for (int i = 0; i < 2; i++)
    argv[i] = malloc(space enough for my integer);
argv[2] = 0;

Where that last line is kind of important to execv

msw
Why would it work in spawn_process_b though? And it's definitely working...the additional process that is called will output results to the screen that prove it's getting the values.
Ryan
This applies to both segments of code. `char *argv[2]` allocates an array of two pointers, but doesn't initialize either pointer.
Thanatos
@Ryan: You're getting lucky. It's undefined behavior - it might work, it might not, depending on the current state of memory.
Thanatos
Thanks, this seemed to get it working. I'm still having something else go wrong, but I think that's another place in the code. Out of curiosity, why is that argv[2] = 0 important for execv? Thanks for your help.
Ryan
@Ryan: Because you don't pass the number of arguments to `execv`, it depends on the final `NULL` to terminate the list.
casablanca
+1 ... lol ... _"kind of important to `execv`"_ ... there's an understatement.
D.Shawley
+3  A: 

You were just lucky that one of the functions actually worked. What you're doing is undefined behaviour in both cases because you haven't allocated memory for the strings you're printing in to.

char *argv[2] only declares an array of 2 character pointers, but they point nowhere. You need to allocate memory for them before you can use them, either statically like this:

char argv[2][100]; // 2 strings of 100 characters each

or dynamically like this:

char *argv[2];
int i;
for (i = 0; i < 2; i++)
  argv[i] = (char *)malloc(100 * sizeof(char)); // 100 characters
casablanca
+1  A: 

Your argv[0] and argv[1] char pointers need to point to something and be initialized.

Frxstrem