gpt4 book ai didi

C:退出函数时丢失字符串

转载 作者:行者123 更新时间:2023-11-30 18:51:44 26 4
gpt4 key购买 nike

我正在尝试实现一个基本的 shell,其中有几个处理字符串的函数,尝试查找文件名,实现相当于 *argv[] 的东西等等。

我在 main() 中有字符串,它们被传递给要填充的函数。接下来,程序返回到 main(),它将字符串传递给另一个要执行操作的函数。

我正在使用lldb进行调试,发现我在第一个函数中成功地使用正确的值填充了字符串,但在退出该函数后,重新进入了main() output_str 字符串再次为 NULL。我认为字符串,因为它们指向内存中的空间,所以会保留值。它们似乎适用于除一种情况之外的所有情况,即下面代码中的 flag = 1 时。

我无法弄清楚发生了什么,因为这些值似乎只在函数的最后 } 之后丢失。

已编辑添加完整代码,希望不要太大。

当我尝试从 stdout 重定向输出时,该代码适用于 cat input.txt,但不适用于 cat input.txt>output.txt 到文件感谢您提前提供的帮助。

这是函数 .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;
}

最佳答案

        output_str = realloc (output_str, (count + 1) * sizeof (char *) );

该行重新分配局部参数变量output_str的值,但新值绝不会返回给 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_strstring_breakdown 返回时很可能无效,因为它没有更新为指向新分配的内存。 这就是为什么您在函数返回时“丢失”字符串值 - output_str变量 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中的调用还有:

             string_breakdown(line, &output_str, count, temp, filename, &f, &saved_stdout, flag, debug); // The call of the above function

因为您正在将指针传递给 mainoutput_str变量,被调用的函数现在可以修改它的值。

您还应该了解string_breakdown正如所写的,修改 line 的字符串参数指向。那是因为它使用 strtok ,和strtok在处理字符串时用 nul 字节替换分隔符。因此,将这个修改后的行缓冲区传递给 com_exec 是很奇怪的。用string_breakdown处理后.

当我尝试编译你的代码时,我收到了几个警告; main.c使用fprintf但没有#include <stdio.h> ,并使用malloc但没有#include <stdlib.h> .

关于C:退出函数时丢失字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36166931/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com