我目前正在研究用C语言编写的一个非常基本的shell。为此,我需要能够将输入字符串分解为“单词”,以便将其发送到execvep()
。为此,我创建了一个函数shishell()
,它需要一个未知长度的字符串,并在内部生成一个字符串数组。由于事先不知道单词的大小及其数量,因此字符串数组是完全动态的。
我遇到的主要问题是这个函数适用于字符串中的1或2个“单词”,但是当我超过3个单词时,它会开始分解,导致分段错误和双重自由损坏错误。
这是一个测试程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int main(int argc, const char *argv[])
{
shishell(argv[1]);
return 0;
}
int fakexec(char** e_input_arr) {
int c = 0;
while(*e_input_arr) {
char* x = *e_input_arr++; c++;
printf(" >%d - %s\n", c, x);
}
}
int shishell(char* e_input) {
int n = 0,
cur_i = 0,
cur_w = 0;
char tmp;
char** input = malloc(sizeof(char*));
input[n] = malloc(sizeof(char));
while ((tmp = e_input[cur_i]) == ' ') {
cur_i++;
}
while ((tmp = e_input[cur_i]) != '\0') {
switch (tmp) {
case ' ':
if (cur_i) {
if (e_input[cur_i-1] != ' ') {
n++;
input = realloc(input, (n+1) * sizeof(char));
input[n] = malloc(sizeof(char));
}
}
cur_w = 0; cur_i++;
break;
default:
input[n] = realloc(input[n], sizeof(char)*cur_w+2);
input[n][cur_w] = e_input[cur_i];
input[n][cur_w+1] = '\0';
cur_w++; cur_i++;
break;
}
printf(">%d - '%c'\n", n, tmp);
}
printf("Pre execuction\n");
fakexec(input);
printf("Post execuction\n");
int j;
for (j = 0; j < n; j++)
free(input[j]);
free(input);
}
此程序需要一个字符串参数。
以下是一些示例输出:
% ./test test
>0 - 't'
>0 - 'e'
>0 - 's'
>0 - 't'
>1 - test
% ./test "hello world"
>0 - 'h'
>0 - 'e'
>0 - 'l'
>0 - 'l'
>0 - 'o'
>1 - ' '
>1 - 'w'
>1 - 'o'
>1 - 'r'
>1 - 'l'
>1 - 'd'
>1 - hello
>2 - world
一切都适合那些人,但接下来:
% ./test "hello world foo"
>0 - 'h'
>0 - 'e'
>0 - 'l'
>0 - 'l'
>0 - 'o'
>1 - ' '
>1 - 'w'
>1 - 'o'
>1 - 'r'
>1 - 'l'
>1 - 'd'
>2 - ' '
>2 - 'f'
>2 - 'o'
>2 - 'o'
>1 - hello
>2 - world
>3 - foo
zsh: segmentation fault (core dumped) ./test "hello world foo"
我认为问题可能来自我对realloc
,malloc
和free
的调用,但是,我并不是因为我正在做我需要它们的实例。
答案 0 :(得分:3)
您的fakexec
功能包括while(*e_input_arr)
。
只有包含空终止条目时,这才能正常工作。但是你不这样做,所以它会读取分配空间的末尾,导致分段错误。
事实上,您没有正确分配input
。行char** input = malloc(sizeof(char*));
仅为input[0]
分配空间。但是,您需要增加n
并继续访问input[1]
等。