我试图在C中创建一个shell,而我却陷入了使内置函数功能化的问题。
这是我的代码:
int my_fork(char *line, char **env)
{
/*char *line = arguments entered in getline() (like 'ls' for example)*/
/*char **env = copy of the shell environment*/
int i = 0;
/*Get the PID for forking*/
pid_t pid = getpid();
/*Declaration of one string and one array*/
char *path = malloc(sizeof(char) * 100);
char **tmp = malloc(sizeof(char *) * 7);
/* my_str_to_word_array transform a string into an array of word*/
char **arg = my_str_to_word_array(line);
for (int j = 0; j < 30; j++)
tmp[j] = malloc(sizeof(char) * 100);
/*my_getpath() search and found the PATH variable in the environment*/
path = my_getpath(env);
/*Then, we put the different paths in an array (paths are separated by ':')*/
tmp = my_str_to_word_array(path);
for (int j = 0; j < 7; j++) {
/*my_strcat() put a string after another string*/
/*Here, i put the entered command after all the paths*/
my_strcat(tmp[j], "/");
my_strcat(tmp[j], arg[0]);
/*my_putstr() print a string, here, i try to print all the modified paths*/
my_putstr(tmp[j]);
write (1, "\n", 1);
}
/*i fork and exec the command*/
pid = fork();
execve(tmp[i], arg, env);
/*i wait until the child process end*/
wait(&pid);
return (0);
}
输出给我一个Segfault信号,我不知道为什么。 Valgrind不帮助我,我现在不知道该怎么办......
我遇到的错误:&#34;不在映射区域0x0和#34;内访问。此错误发生在&my; my_strlen()&#39;中,这些函数计算字符串的长度。我已经搜索了为什么会出现这个错误,而且我不明白,因为在我的字符串末尾,我一定会有&#39; \ 0&#39;。
my_strcat():
char *my_strcat(char *dest, char *src)
{
int i = 0;
int len = my_strlen(dest);
for (; src[i] != '\0'; i++)
dest[len + i] = src[i];
i++;
dest[len + i] = '\0';
return (dest);
}
my_strlen():
int my_strlen (char *str)
{
int i = 0;
while (str[i])
i++;
return (i);
}
所以,总而言之,我想让内置函数起作用,我在my_strlen()中有一个错误,它不是我唯一的错误,但是现在,让我们来看看留意这个。
答案 0 :(得分:0)
my_str_to_word_array():
char **my_str_to_word_array(char *str)
{
int i = 0;
int j = 0;
int m = 0;
int len = my_strlen(str);
char **tmp = malloc(sizeof(char *) * 10);
for (int n = 0; n < 10; n++)
tmp[n] = malloc(sizeof(char) * 50);
while (j < len) {
m = 0;
while ((str[j] == ':') || (str[j] == ' ') || (str[j] == '\n'))
j++;
while ((str[j] != ':') && (str[j] != ' ') && (str[j] != '\n'))
tmp[i][m++] = str[j++];
tmp[i][m + 1] = '\0';
i++;
}
tmp[i] = NULL;
return (tmp);
}
my_getpath():
char *my_getpath(char **env)
{
int i = 0;
char *tmp = NULL;
int len = 0;
while (my_strncmp(env[i], "PATH=", 5) != 0)
i++;
len = my_strlen(env[i]);
env[i][len + 1] = '\0';
tmp = malloc(sizeof(char) * my_strlen(env[i]));
my_printf("Path found\nLen: %d\n", my_strlen(env[i]));
my_printf("Path: ");
my_putstr(env[i]);
write(1, "\n", 1);
tmp = my_strncpy(tmp, env[i], 5);
return (tmp);
}
my_strncpy():
char *my_strncpy (char *src, int n)
{
int i = 0;
char *dest = malloc(sizeof(char));
int len = my_strlen(src);
for (; n <= len; i++) {
dest[i] = src[n];
n++;
}
dest[i] = '\0';
return (dest);
}
getpath()之后的路径打印给了我一个Segfault,当我看valgrind时,它告诉我它是因为my_strlen()。
但是当我不打印它时它会起作用,所以我不会因为my_strlen()而认为它。
输出:
路径发现
Len:124
路径:PATH = / usr / lib64 / qt-3.3 / bin:/ usr / local / bin:/ usr / bin:/ bin:/ usr / local / sbin:/ usr / sbin:/home/tyrone/.local/ bin:/ home / tyrone / bin分段错误(核心转储)
当我看到这个时,我认为它在my_strncpy中,但我不知道错误的位置。
答案 1 :(得分:0)
您的代码还存在其他一些问题,最终也会导致问题。
首先,此代码在使用fork()
:
/*i fork and exec the command*/
pid = fork();
execve(tmp[i], arg, env);
/*i wait until the child process end*/
wait(&pid);
return (0);
当fork()
有效时,之后会有两个进程。 pid
中保留的返回值为零的一个。这是新创建的子进程。在原始父进程中,pid
将是新创建的子进程的进程ID。 (如果pid
的值为( pid_t ) -1
,则表示对fork()
的调用失败 - 只会返回原始父进程。
所以你的代码需要做这样的事情:
pid = fork();
// parent process
if ( pid == 0 )
{
execve(tmp[i], arg, env);
// if you get here, execve() failed and you need
// to be really careful because you're now running
// a copy of the parent process - you can corrupt
// files open in the parent, for example, because
// data can be buffered in FILE * streams.
// this is safe, though. Note the underscore!
// exit(0) without the underscore is *not* safe here
_exit(0);
}
// child process
else if ( pid > ( pid_t ) 0 )
{
wait(&pid);
}
else
{
// fork() failed - handle error
}
return (0);
另外,当你分配一个像这样的字符串数组时:
char **tmp = malloc(sizeof(char *) * 7);
for (int j = 0; j < 30; j++)
tmp[j] = malloc(sizeof(char) * 100);
然后执行此操作:
tmp = my_str_to_word_array(path);
您刚刚通过覆盖char **tmp = malloc(...);
来自malloc()
的{{1}}调用返回的值泄露了您分配的所有内存。一旦泄漏,泄漏了循环中malloc()
调用中分配的所有内存。