下面这个代码是实现一个自己的shell中的一段代码,但是运行后发生了段错误,请问应该怎么改正呢
#include "shell.h"
#define TOK_DELIM " "
#define TOK_BUFFER_SIZE 64
#include <malloc.h>
char ** split_line(char *buffer);
int search_command(char **tokens);
int change_directory(char **tokens);
int exit_command(char* buffer);
int display_former_command(node* n);
int find_command_with_prefix(char **tokens);
int list_files();
/**
* shell的入口
*/
void prefix() {
char cwd[255];
getcwd(cwd, sizeof(cwd));
printf("%s$ ", cwd);
}
int execute(char* buffer) {
char **tokens = split_line(buffer);
if(strcmp(tokens[0] , "cd") == 0) {
return change_directory(tokens);
}else if(strcmp(tokens[0] , "exit") == 0) {
return exit_command(buffer);
}else if(strcmp(tokens[0] , "!#") == 0) {
return display_former_command(Log.head);
}else if(tokens[0][0] == '!' && tokens[0][1] != '#') {
return find_command_with_prefix(tokens);
}else if(strcmp(tokens[0] , "ls") == 0) {
return list_files();
}else{
return search_command(tokens);
}
free(tokens);
tokens=NULL;
return 1;
}
char ** split_line(char *buffer){
int buffer_size = TOK_BUFFER_SIZE;
char **tokens = (char **)malloc(buffer_size*sizeof(char *));
int id = 0;
char *token = (char *)malloc(buffer_size*sizeof(char));
token = strtok(buffer, TOK_DELIM);
for(id=0; token != NULL; id++){
strcpy(tokens[id], token);
token = strtok(NULL, TOK_DELIM);
}
free(token);
token = NULL;
tokens[id]=NULL;
return tokens;
}
int search_command(char **tokens){
char tokens_sh[100]={'\0'};
if(strcmp(tokens[0], "args") != 0){
strcpy(tokens_sh, "./");
}
strcat(tokens_sh, tokens[0]);
int pid = fork();
if(pid == 0){ // child process
if(execvp(tokens_sh, tokens[0]) < 0){
printf("%s: no such command\n", tokens[0]);
}
exit(1);
}else{
log_push(&Log, tokens[0]);
wait(pid);
}
return 1;
}
int change_directory(char **tokens){
char dir[255];
strcpy(dir, tokens[1]);
if(chdir(dir)) {
printf("%s: No such file or directory\n", tokens[1]);
}
log_push(&Log,tokens[1]);
return 1;
}
int exit_command(char* buffer){
free(buffer);
return 0;
}
int display_former_command(node* n) {
if(n==NULL)
return 1;
display_former_command(n->next);
printf("%s\n",n->cmd);
return 1;
}
int find_command_with_prefix(char **tokens){
char* search = log_search(&Log, tokens[0]+1);
if(search != NULL) {
log_push(&Log, search);
execute(search);
} else {
printf("No Match\n");
}
return 1;
}
int list_files(){
log_push(&Log, "ls");
system("ls");
return 1;
}
贴出错误信息啊,是异常还是代码自己给的错误提示?
报错信息 提供一下呦
shell程序要特别注意内存管理,谨慎使用malloc/free,避免频繁的内存分配和释放。适当使用Valgrind等工具帮助检测内存错误。
// 在split_line()中,释放为token分配的内存
free(token);
// 在execute()结束时,释放tokens内存
free(tokens);
// 在search_command()中,将execvp的参数改为tokens
execvp(tokens_sh, tokens);
错误显示在哪
错误信息和截图发出来,这样看怎么定位?
哪里错误,是啥错误
运行报错说下,再改
1)kill -信号的序号 进程的id
例如 kill -9 20000
kill -KILL 20000
kill -SIGINT 20000
2)killall -信号的序号 进程的名字
ctrl + c默认给当前进程发送了SIGINT信号
在split_line函数中,你没有为tokens[id]分配内存,而是直接使用strcpy函数。这会导致内存访问越界,导致段错误。你应该在循环中为每个tokens[id]分配足够的空间,或者使用strdup函数来复制字符串
看下是不是这个问题
char ** split_line(char *buffer){
int buffer_size = TOK_BUFFER_SIZE;
char **tokens = (char **)malloc(buffer_size*sizeof(char *));
int id = 0;
char *token = (char *)malloc(buffer_size*sizeof(char));
token = strtok(buffer, TOK_DELIM);
for(id=0; token != NULL; id++){
// 为tokens[id]分配内存
tokens[id] = (char *)malloc(strlen(token) + 1);
// 或者使用strdup函数
// tokens[id] = strdup(token);
strcpy(tokens[id], token);
token = strtok(NULL, TOK_DELIM);
}
free(token);
token = NULL;
tokens[id]=NULL;
return tokens;
}
把你运行报错得贴出来,不然不好整
Compile error: /storage/emulated/0/Android/data/com.cjkj.clanide/files/CJ_IDE/CProject/CIDEExample/src/Main.c:2:10: fatal error: shell.h: No such file or directory
#include "shell.h"
^~~~~~~~~
compilation terminated.
以上为你的代码的错误信息
你的错误可能是头文件引入的问题,检查下头文件是否能够正确引入并使用。其次,检查下在 split_line 函数的最后,你释放了 token 指针,但是之前分配的 tokens 指针并没有被释放。这里可能也会有问题。
具体报什么错呢,看看报错信息
1.在split_line()函数中,将分割后的子字符串存储到tokens数组时,应该使用动态分配的内存。当前代码中,只是将指针赋值给tokens数组中的元素,这可能导致访问非法内存或者出现未定义的行为。你可以使用malloc()来动态分配内存,然后使用strcpy()将分割后的字符串复制到分配的内存空间中。
2.在search_command()函数中,execvp()函数的第一个参数应该是可执行文件的路径,而不仅仅是命令的名称。当前代码中,将命令名称直接传递给了execvp(),这可能导致找不到命令。你可以构建完整的路径,如./command,然后将其作为execvp()的第一个参数。
3.在exit_command()函数中,释放内存时使用了错误的函数。buffer是通过malloc()动态分配的,应该使用free()来释放,而不是直接使用delete。
4.在display_former_command()函数中,递归调用时,应该先打印出当前节点的命令,然后再递归调用下一个节点,以保证按照倒序显示命令。
5.在execute()函数最后释放tokens的操作,永远不会执行到,因为在之前的分支中都已经return了。所以这行代码实际上是无用的。
采用chatgpt:
在代码中有几个问题需要修正:
1、malloc.h 库已经过时,应该使用 stdlib.h 库来包含 malloc 函数的声明。
2、split_line 函数中,你分配了 tokens 数组来存储分割后的字符串,但是没有为每个元素分配内存空间。在循环中使用 strcpy 函数之前,需要为 tokens[id] 分配内存空间。你可以使用 malloc 函数来为每个元素分配适当的内存空间。
3、在 search_command 函数中,execvp 函数的第二个参数应该传递整个 tokens 数组,而不仅仅是 tokens[0]。修改为 execvp(tokens_sh, tokens)。
4、wait 函数应该传递一个指向整型变量的指针作为参数,而不是进程ID。你可以使用 waitpid 函数来等待子进程结束,如下所示:
waitpid(pid, NULL, 0);
在 execute 函数的末尾,释放 tokens 数组的内存应该放在最后一行的前面。
修改后的代码如下所示:
#include "shell.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define TOK_DELIM " "
#define TOK_BUFFER_SIZE 64
char **split_line(char *buffer);
int search_command(char **tokens);
int change_directory(char **tokens);
int exit_command(char *buffer);
int display_former_command(node *n);
int find_command_with_prefix(char **tokens);
int list_files();
/**
* shell的入口
*/
void prefix() {
char cwd[255];
getcwd(cwd, sizeof(cwd));
printf("%s$ ", cwd);
}
int execute(char *buffer) {
char **tokens = split_line(buffer);
if (strcmp(tokens[0], "cd") == 0) {
return change_directory(tokens);
} else if (strcmp(tokens[0], "exit") == 0) {
return exit_command(buffer);
} else if (strcmp(tokens[0], "!#") == 0) {
return display_former_command(Log.head);
} else if (tokens[0][0] == '!' && tokens[0][1] != '#') {
return find_command_with_prefix(tokens);
} else if (strcmp(tokens[0], "ls") == 0) {
return list_files();
} else {
return search_command(tokens);
}
free(tokens);
return 1;
}
char **split_line(char *buffer) {
int buffer_size = TOK_BUFFER_SIZE;
char **tokens = (char **)malloc(buffer_size * sizeof(char *));
int id = 0;
char *token;
token = strtok(buffer, TOK_DELIM);
while (token != NULL) {
tokens[id] = (char *)malloc(strlen(token) + 1);
strcpy(tokens[id], token);
token = strtok(NULL, TOK_DELIM);
id++;
}
tokens[id] = NULL;
return tokens;
}
int search_command(char **tokens) {
char tokens_sh[100] = {'\0'};
if (strcmp(tokens[0], "args") != 0) {
strcpy(tokens_sh, "./");
}
strcat(tokens_sh, tokens[0]);
int pid = fork();
if (pid == 0) { // child process
if (execvp(tokens_sh, tokens) < 0) {
printf("%s: no such command\n", tokens[0]);
}
exit(1);
} else {
log_push(&Log, tokens[0]);
waitpid(pid, NULL, 0);
}
return 1;
}
int change_directory(char **tokens) {
char dir[255];
strcpy(dir, tokens[1]);
if (chdir(dir)) {
printf("%s: No such file or directory\n", tokens[1]);
}
log_push(&Log, tokens[1]);
return 1;
}
int exit_command(char *buffer) {
free(buffer);
return 0;
}
int display_former_command(node *n) {
if (n == NULL)
return 1;
display_former_command(n->next);
printf("%s\n", n->cmd);
return 1;
}
int find_command_with_prefix(char **tokens) {
char *search = log_search(&Log, tokens[0] + 1);
if (search != NULL) {
log_push(&Log, search);
execute(search);
} else {
printf("No Match\n");
}
return 1;
}
int list_files() {
log_push(&Log, "ls");
system("ls");
return 1;
}
这些修改应该能够解决段错误问题。但请注意,在修改代码之前,最好先确认段错误的原因,并检查其他可能导致问题的因素。