C:退出函数时丢失字符串
我正在尝试实现一个基本的shell,其中有几个处理字符串的函数,尝试查找文件名,实现与C:退出函数时丢失字符串,c,string,function,unix,C,String,Function,Unix,我正在尝试实现一个基本的shell,其中有几个处理字符串的函数,尝试查找文件名,实现与*argv[]等价的东西等等 我在main()中有字符串,这些字符串被传递给要填充的函数。接下来,程序返回到main(),它将字符串传递给另一个要执行操作的函数 我正在使用lldb进行调试,发现我在第一个函数中成功地用正确的值填充字符串,但在退出该函数后,重新输入main()时,output\u str字符串再次为NULL。我认为字符串会保留值,因为它们指向内存中的空间。在下面的代码中,当flag=1时,它们似
*argv[]
等价的东西等等
我在main()
中有字符串,这些字符串被传递给要填充的函数。接下来,程序返回到main()
,它将字符串传递给另一个要执行操作的函数
我正在使用lldb
进行调试,发现我在第一个函数中成功地用正确的值填充字符串,但在退出该函数后,重新输入main()
时,output\u str
字符串再次为NULL
。我认为字符串会保留值,因为它们指向内存中的空间。在下面的代码中,当flag=1时,它们似乎只适用于一种情况
我不知道发生了什么,因为值似乎只有在函数的最后一次}
之后才会丢失
编辑添加完整的代码,希望不要太大
当我尝试将输出从stdout
重定向到一个文件时,代码可以使用,比如,cat input.txt
,但不能使用cat input.txt>output.txt
提前谢谢你的帮助
下面是function.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);
}
}
下面是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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“shell.h”
内部主(空)
{
int-debug=0;
char*line=NULL;
尺寸长度=0;
ssize_t read=0;
int标志=0;
int f=0;
保存的int_stdout=0;
做
{
flag=0;
//读取=提示(行、列、读取);
字符缓冲区[15];
time\u t now=时间(空);
strftime(缓冲区,15,“[%d/%m%H:%m]”,localtime(&now));
fprintf(标准输出,“%s#”,缓冲区);
信号(信号,信号);
read=getline(&line,&len,stdin);
信号(SIGINT、SIG_DFL);
flag=检查\u重定向(行、标志);
char**output_str=malloc(sizeof(char*));
整数计数=0;
char*temp=NULL;
char*filename=malloc(sizeof(char*));
字符串分解(行、输出、计数、临时、文件名、&f、&saved、标准输出、标志、调试);//问题函数的函数调用
com_exec(行、输出、文件名、f和保存的标准输出、标志、调试);
}while(read!=EOF);
if(debug)fprintf(stderr,“父级退出\n”);
else fprintf(标准输出,“\n”);
返回0;
}
您的realloc什么都不做
你的意思是*输出\u 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
这一行重新分配了本地参数变量output\u str
的值,但新值不会返回到string\u breakdown
函数的调用者-这意味着它的指针可能会悬空,并且在使用时会导致问题(“未定义的行为”),表现为奇怪的程序行为或崩溃)
您需要了解,在函数中,output\u str
是一个局部变量。您可以更改其值,但这不会影响调用者中任何变量的值
从main
调用函数:
string_breakdown(line, output_str, count, temp, filename, &f, &saved_stdout, flag, debug); // The call of the above function
main
也使用output\u str
作为变量名,但这是另一个变量。一个变量是main
的本地变量,另一个是string\u-breakdown
的本地变量,即使它们共享相同的名称。由于上面的realloc
调用,main
的output\u str
中的指针值在从string\u breakdown
返回时很可能无效,因为它没有更新为指向新分配的内存这就是为什么从函数返回时“丢失”字符串值的原因-main
中的output\u str
变量不再实际指向字符串数组,该数组已通过realloc
移动到其他位置
通常,您可以通过添加另一个间接级别来解决此类问题,将output\u 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)
及
及
等等。您还需要在main
中调整调用:
string_breakdown(line, &output_str, count, temp, filename, &f, &saved_stdout, flag, debug); // The call of the above function
由于您正在传递一个指向main
的output\u str
变量的指针,因此被调用函数现在可以修改其值
您还应该了解,string\u writed
会修改行
参数所指向的字符串。这是因为它使用strtok
,并且strtok
在处理字符串时用nul字节替换分隔符。因此,在使用string\u-breakdown
对其进行处理后,将修改后的行缓冲区传递给com\u-exec
,这很奇怪
当我试图编译你的代码时,我收到了几个警告
main.c
使用fprintf
但不包含\include
,使用malloc
但不包含\include此函数中的哪个字符串?向我们展示调用代码Too当您声明字符串是string_breakdown()函数的本地字符串时,您需要根据main()需要返回*delim或*sep,并将此函数的返回类型更改为char*@pm100。我添加了函数调用code@ArifBurhan那两个人是不需要的,这就是为什么它们是本地的output\u str=realloc(output\u str,
:永远不要在调用者端更新output\u str
。我能问一下*output\u str有什么不同吗?*output\u ptr=says-存储这一点吗
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 *) );
string_breakdown(line, &output_str, count, temp, filename, &f, &saved_stdout, flag, debug); // The call of the above function