I'm having trouble catching what I'm doing wrong inserting strings into an array in C. Below is the code. The printf lines show me that I am indeed reading the correct data -- but after I stick each line of data into an array -- I then inspect it to find that every element of the array is filled with the last line put into the array.
//Code snippet
char outbuf[BUFFER_LEN];
int std_out_count = 0;
char *std_out_lines[BUFFER_LEN]; /* Array to hold STDOUT */
while ((i = read(stdout_pipe_fds[0], outbuf, BUFFER_LEN - 1)) > 0) {
outbuf[i] = '\0';
char temp[BUFFER_LEN];
printf("PARENT read from stdout: %s\n", outbuf);
strcpy(temp, outbuf);
std_out_lines[std_out_count] = temp;开发者_开发百科
std_out_count++;
}
printf("STDOUT_COUNT: %i\n", std_out_count); /* Print out elements of array to make sure they're correct */
int idx;
for(idx = 0; idx < std_out_count; idx++) {
printf("STDOUT[%i]: %s\n", idx, std_out_lines[idx]);
}
// I can see by this output that I'm reading the correct values
/* PARENT read from stdout: STDOUT = :this is line number 0:
PARENT read from stdout: STDOUT = :this is line number 1:
PARENT read from stdout: STDOUT = :this is line number 2: */
// But when I inspect the elements of the array -- every element is filled with the last line read ;(
/* STDOUT_COUNT: 3 STDOUT[0]: STDOUT = :this is line number 2:
STDOUT[1]: STDOUT = :this is line number 2:
STDOUT[2]: STDOUT = :this is line number 2: */
This line:
char *std_out_lines[BUFFER_LEN];
allocates an array of character pointers but does not allocate any space for the actual data itself.
Later on, when you do:
char temp[BUFFER_LEN];
printf("PARENT read from stdout: %s\n", outbuf);
strcpy(temp, outbuf);
std_out_lines[std_out_count] = temp;
you're actually overwriting the same piece of memory which each new line and storing its (unchanging) address into the next character pointer.char temp[BUFFER_LEN];
doesn't give you a new data area every time it executes.
That's why it appears to be working. However, when temp
goes out of scope, I wouldn't suggest trying to examine any of the lines pointed at by your array. It's undefined behaviour. It seems to be working for you but I'll guarantee that's purely by accident :-)
What you may want to look at is duplicating the string so that each array element has its own copy. Replace:
std_out_lines[std_out_count] = temp;
with:
std_out_lines[std_out_count] = strdup(temp);
or, just ditch temp
altogether and use:
std_out_lines[std_out_count] = strdup(outbuf);
This makes a copy of the string, and gives you the address of it for storing into the array, so that they're all separate from each other. Just remember that you should probably free that memory eventually.
On the off-chance that your C implementation doesn't have a strdup
(it's not mandated by the ISO standard), here's one I prepared earlier.
You need to allocate some storage rather than use the temp temporary variable.
At present you are re-using the temp variable each time round the loop.
Use something like
std_out_lines[i] = malloc(BUFFER_LEN);
// check for null here too, malloc can fail.
You are inserting a pointer to a stack allocated buffer 'temp', which most of the time will be the same pointer.
Change your while loop code to:
outbuf[i] = '\0';
printf("PARENT read from stdout: %s\n", outbuf);
std_out_lines[std_out_count] = strdup(outbuf);
std_out_count++;
strdup() will allocate storage for the string inserted into std_out_lines array and copy the contents of outbuf into that new string.
精彩评论