我正在编写一个处理管道的 shell。我得到用户输入并根据输入的管道(如果有的话)将其分成几段并将其放入数组中。数组中的第一项是数组中存储为字符串的元素数。 fork 后,数组中的第一个元素在父进程和子进程中都显示为零或空值。
代码
char *getInput(void)
{
int bufferSize = 1024;
char *buffer = malloc(sizeof(char) * bufferSize);
int counter = 0;
int c = getchar();
// Loop through each character in input
while (c != EOF && c != '\n')
{
// Ensure that the buffer can fit the next char
if (counter <= bufferSize) // If buffer not full
{
buffer[counter] = c; // Add character to buffer
}
else // If buffer full
{
bufferSize = bufferSize + 1024; // Increase buffer size
buffer[counter] = c; // Add character to buffer
}
c = getchar(); // Get the next char
counter++;
}
// Add null to end of buffer
if (counter <= bufferSize) // If buffer not full
{
buffer[counter] = '\0'; // Add null character to end of buffer
}
else // If buffer full
{
bufferSize = bufferSize + 1024; // Calculate new buffer size
buffer = realloc(buffer, bufferSize); // Increase buffer size
buffer[counter] = '\0'; // Add null character to end of buffer
}
return buffer;
}
char **split(char *input, char *delimiter)
{
int counter = 0;
int bufferSize = 1024;
//char d[2] = delimiter; // Delimit string by spaces
char *item = strtok(input, delimiter); // Gets first delimited item
// Array of items, allocate extra slot to store array size
char **itemArray = malloc((sizeof(char) * bufferSize) + 1);
while (item != NULL) // While items left in string
{
itemArray[counter+1] = item; // Insert into array of items
item = strtok(NULL, delimiter); // Get next delimited item
counter++;
if (counter <= bufferSize) // If buffer not full
{
bufferSize = bufferSize + 1024; // Calculate new buffer size
itemArray = realloc(itemArray, bufferSize); // Increase buffer size
}
}
// Store size of array in first array slot
char size = counter + 48;
char *sizeP = &size;
itemArray[0] = sizeP;
return itemArray;
}
int main(int argc, char *argv[])
{
int loop = 1;
char *input;
char **segs;
// Loop until the EOF command is used
while (loop)
{
input = getInput(); // Get input line
char *delimiter = "|";
segs = split(input, delimiter); // Parse for pipe segments or single segment
if (segs[1] == NULL) return 0; // EOF
char *segsSizeChar1 = segs[0];
int numSegs1 = *segsSizeChar1 - '0';
printf("\nBefore Fork:\n");
printf("Arr[0]: %i\n", numSegs1);
printf("Arr[1]: %s\n", segs[1]);
// Initial Fork
pid_t pid;
pid = fork();
if (pid > 0) // Parent
{
char *segsSizeChar2 = segs[0];
int numSegs2 = *segsSizeChar2 - '0';
printf("\nIn Parent:\n");
printf("Arr[0]: %i\n", numSegs2);
printf("Arr[1]: %s\n", segs[1]);
}
else if (pid == 0) // Child
{
char *segsSizeChar3 = segs[0];
int numSegs3 = *segsSizeChar3 - '0';
printf("\nIn Child:\n");
printf("Arr[0]: %i\n", numSegs3);
printf("Arr[1]: %s\n", segs[1]);
}
else
{
// Catch error
}
}
}
输入
ls
输出
Before Fork:
Arr[0]: 1
Arr[1]: ls
In Parent:
Arr[0]: -48
Arr[1]: ls
In Child:
Arr[0]: -48
Arr[1]: ls
正如您在父项和子项中看到的那样,arr[0] 具有零值或空值而不是 1(它应该只有一个,因为只有一个段,没有管道)。 奇怪的是,数组的其余部分似乎没问题,因为选择下一个数组元素会显示正确的值。
这个问题似乎是在我 fork 之后直接发生的,但我不确定为什么。
最佳答案
问题是由以下几行引起的:
// Store size of array in first array slot
char size = counter + 48;
char *sizeP = &size;
itemArray[0] = sizeP;
您正在从 split
返回局部变量 size
的地址,并且正在取消引用地址:
char *segsSizeChar1 = segs[0];
int numSegs1 = *segsSizeChar1 - '0';
和
char *segsSizeChar2 = segs[0];
int numSegs2 = *segsSizeChar2 - '0';
和
char *segsSizeChar3 = segs[0];
int numSegs3 = *segsSizeChar3 - '0';
这是未定义行为的原因。
您可以通过将 split
中的那些行更改为:
char *sizeP = malloc(1);
*sizeP = counter + 48;
itemArray[0] = sizeP;
关于c - 二维字符串数组中第一个元素的值在 fork 后意外更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28512858/