我试图实现一个基本的shell,我有几个处理字符串的函数,试图找到文件名,实现等同于*argv[]
的东西等等。
我在main()
中有字符串,它们被传递给要填充的函数。接下来,程序返回main()
,它将字符串传递给另一个要作用的函数。
我正在使用lldb
进行调试,发现我在第一个函数中使用正确的值成功填充了字符串,但在退出函数时,重新输入main()
output_str
字符串再次NULL
。我认为字符串,因为它们指向内存中的空间将保留值。在下面的代码中,当flag = 1时,它们似乎只有一种情况。
我无法弄清楚发生了什么,因为价值似乎只是在函数的最后}
之后丢失了。
编辑添加完整代码,希望它不会太大。
当我尝试将输出从cat input.txt
重定向到文件时,代码与cat input.txt>output.txt
合作,但不与stdout
一起使用
感谢您的帮助。
这是函数.c文件:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
void sig_handler(int signo)
{
if (signo == SIGINT)
{
fprintf(stdout, "\n");
fflush(stdout);
}
}
int check_redirect(char *line, int flag)
{
int n = 0;
if (line == NULL) return (flag);
else
{
do
{
if (line[n] == '>') flag = 1;
n++;
}while (line[n] != '\0');
}
return (flag);
}
void string_breakdown(char *line, char **output_str, int count, char* temp, char *filename, int *f, int *saved_stdout, int flag, int debug)
{
char *sep = " \n";
char *delim = ">\n";
if (line != NULL)
{
temp = strtok(line, delim);
while (temp != NULL)
{
output_str[count] = temp;
if (debug) fprintf(stderr, "1:%s\n2:%s\n3:%s\n", line, temp, output_str[count]);
count++;
output_str = realloc (output_str, (count + 1) * sizeof (char *) );
temp = strtok(NULL, delim);
}
if (flag)
{
count = 0;
strcpy(filename, output_str[1]);
output_str[1] = NULL;
*saved_stdout = dup(1);
*f = open(filename , O_WRONLY|O_CREAT|O_TRUNC, 0666);
dup2(*f, 1);
temp = strtok(*output_str[0], sep);
while (temp != NULL)
{
output_str[count] = temp;
//if (debug) fprintf(stderr, "1:%s\n2:%s\n3:%s\n", line, temp, output_str[count]);
count++;
output_str = realloc (output_str, (count + 1) * sizeof (char *));
temp = strtok(NULL, sep);
}
}
else
{
count = 0;
temp = strtok(line, sep);
while (temp != NULL)
{
output_str[count] = temp;
if (debug) fprintf(stderr, "1:%s\n2:%s\n3:%s\n", line, temp, output_str[count]);
count++;
output_str = realloc (output_str, (count + 1) * sizeof (char *));
temp = strtok(NULL, sep);
}
}
}
}
void com_exec(char *line, char **output_str, char *filename, int *f, int *saved_stdout, int flag, int debug)
{
char *command = malloc(sizeof(char *));
command = output_str[0];
char *name = "HOME";
int ret_val = 0;
pid_t child_pid;
int child_status;
if (command == NULL);
else if (strcmp("cd", command) == 0)
{
if (output_str[1] == NULL) output_str[1] = getenv(name);
ret_val = 0;
ret_val = chdir(output_str[1]);
if (ret_val) perror(NULL);
}
else
{
child_pid = fork ();
if (child_pid == 0)
{
if (debug)
{
system(line);
fprintf(stderr, "Post System Pre Exec\n1:%s\n2:%s\n3:%s\n", line, output_str[0], command);
sleep(2);
}
execvp(command, output_str);
if (flag)
{
close(*f);
dup2(*saved_stdout, 1);
close(*saved_stdout);
}
fprintf (stdout, "Unknown command\n");
exit (0);
}
else
{
if (flag)
{
close(*f);
dup2(*saved_stdout, 1);
close(*saved_stdout);
}
signal(SIGINT, sig_handler);
usleep(500000);
//Parent process waits for child to finish
if (debug) fprintf (stderr, "parent waiting\n");
wait(&child_status);
waitpid(child_pid, &child_status, 0);
signal(SIGINT, SIG_DFL);
}
}
这是函数.h文件:
#ifndef SHELL_H_INCLUDED
#define SHELL_H_INCLUDED
void sig_handler(int signo);
int prompt(char *line, size_t len, ssize_t read);
int check_redirect(char *line, int flag);
void string_breakdown(char *line, char **output_str, int count, char* temp, char *filename, int *f, int *saved_stdout, int flag, int debug);
void com_exec(char *line, char **output_str, char *filename, int *f, int *saved_stdout, int flag, int debug);
#endif // LINKLAYER_H_INCLUDED
下面是main.c,其中调用了函数。
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include "shell.h"
int main(void)
{
int debug = 0;
char *line = NULL;
size_t len = 0;
ssize_t read = 0;
int flag = 0;
int f = 0;
int saved_stdout = 0;
do
{
flag = 0;
//read = prompt(line, len, read);
char buffer[15];
time_t now = time(NULL);
strftime(buffer, 15, "[%d/%m %H:%M]", localtime(&now) );
fprintf(stdout, "%s # ", buffer);
signal(SIGINT, SIG_IGN);
read = getline (&line, &len, stdin);
signal(SIGINT, SIG_DFL);
flag = check_redirect(line, flag);
char **output_str = malloc(sizeof(char *));
int count = 0;
char* temp = NULL;
char *filename = malloc(sizeof(char *));
string_breakdown(line, output_str, count, temp, filename, &f, &saved_stdout, flag, debug); // function call of problem function
com_exec(line, output_str, filename, &f, &saved_stdout, flag, debug);
} while (read != EOF);
if (debug) fprintf(stderr, "parent exiting\n");
else fprintf(stdout, "\n");
return 0;
}
答案 0 :(得分:2)
function foo(input) {
return {
set: function(key, value) {
input[key] = value;
console.log(input);
},
get: function(key) {
return input[key];
},
assign: function(object) {
input = Object.assign({}, object);
console.log(input);
}
};
};
var obj = {},
bar = foo(obj);
bar.set('x', 1); // {x: 1}
console.log(obj); // {x: 1}
bar.set('y', 2); // {x: 1, y: 2}
console.log(obj); // {x: 1, y: 2} so far so good
bar.assign({ // {a: 5, b: 10}
a: 5,
b: 10
});
console.log(obj); // {x: 1, y: 2} supposed to be {a: 5, b: 10} but it was not
bar.assign({ // {a: 15}
a: 15
});
console.log(obj); // {x: 1, y: 2} didn't change at all
bar.set('b', 20); // {a: 15, b: 20}
console.log(obj); // {x: 1, y: 2}
console.log(bar.get('a')); // 15
此行重新分配本地参数变量 output_str = realloc (output_str, (count + 1) * sizeof (char *) );
的值,但新值绝不会使其返回output_str
函数的调用者 - 意味着指针< em> has 可能会悬空,并且在使用时会导致问题(&#34;未定义的行为&#34;,表现为奇怪的程序行为或崩溃)。
您需要了解在函数内,string_breakdown
是一个局部变量。您可以更改其值,但这不会影响调用者中任何变量的值。
您从output_str
调用该函数:
main
string_breakdown(line, output_str, count, temp, filename, &f, &saved_stdout, flag, debug); // The call of the above function
也使用main
作为变量名称,但同样,这是不同的变量。一个变量是output_str
的本地变量,另一个变量是main
的本地变量,即使它们具有相同的名称。由于上面的string_breakdown
调用,realloc
main
中的指针值很可能在从output_str
返回时无效,因为它未更新为指向新分配的内存。 这就是为什么你&#34;失去&#34;从函数返回时的字符串值 - string_breakdown
中的output_str
变量不再实际指向字符串数组,字符串数组已通过{{1}移动到其他位置}。
通常,您可以通过添加其他级别的间接来解决此类问题,将main
参数从realloc
更改为output_str
:
char **
和
char ***
和
void string_breakdown(char *line, char ***output_str, int count, char* temp, char *filename, int *f, int *saved_stdout, int flag, int debug)
等等。您还需要在 (*output_str)[count] = temp;
中调整呼叫:
*output_str = realloc (*output_str, (count + 1) * sizeof (char *) );
因为您将指针传递给main
的{{1}}变量,所以被调用函数现在可以修改其值。
您还应该了解写入的 string_breakdown(line, &output_str, count, temp, filename, &f, &saved_stdout, flag, debug); // The call of the above function
会修改main
参数指向的字符串。这是因为它使用output_str
,而string_breakdown
在处理字符串时用nul字节替换分隔符。因此,在使用line
处理后,将此修改后的行缓冲区传递给strtok
,这很奇怪。
当我尝试编译代码时,我收到了几个警告; strtok
使用com_exec
,但不是string_breakdown
,并使用main.c
但不是fprintf
。
答案 1 :(得分:0)
你的realloc什么都不做。
你的意思是*output_ptr = realloc....
实际上它做了一些事情,但真的很糟糕
这也是错误的
output_str[count] = temp;
和这个
filename = output_str[1];
你需要区分 - 指向缓冲区的指针,指向缓冲区指针的指针。
char * buffer = *output_str; // to remove the confusion
strcpy(&buffer[count], temp); // assigning pointers doesnt copy things
filename = buffer[1]; // is hat what you mean - filename is one char