- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试实现一个基本的 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_str
从 string_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
因为您正在将指针传递给 main
的output_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/
我在 Ubuntu 10.04 LTS 上运行 Eclipse Galileo。今天 Ubuntu 在我身上崩溃了,重新启动后,我发现 Eclipse 已经完全失去了 Java Perspective
我使用配置了 sonata_user 的 SonataAdminBundle在 config.yml : sonata_user: impersonating: route:
我有 ubuntu 14.04 但它不见了 docker exec sudo docker exec -it ubuntu_bash bash 我希望在现有正在运行的 docker 容器中运行交互式
我正在使用 Ubuntu 8.04/32 位(作为虚拟机)。在一个不是 min 的项目上执行一些 make 时,我得到了错误: g++:/usr/lib/libstdc++.a: 没有这样的文件或目录
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问题,使其成为
我正在尝试获取有关我在 UIImagePicker 中选择的视频的一些数据。 因此,当它进入 UIImagePicker 委托(delegate)方法(如下)时,我知道我需要使用信息字典中的 UIIm
我的网站最近被可能的黑客行为删除了。我上传了备份的文件夹和数据库,但现在我的 View 没有显示。其他一切都有效。我想不出有什么变化,只是上传了几天前的备份。 这些字段在 admin/build/vi
我执行以下操作来设置我的 session ,这是有效的,因为 echo 出现了。但是当我转到下一页或另一页时, session 不存在吗?我做错了什么? $session_start(); if ($
我试图在 BigQuery 中使用这段代码,显然是从 GA 中获取数据,但 _TABLE_SUFFIX 似乎有问题。错误显示“错误:无法识别的名称:_TABLE_SUFFIX at [12:3]”您能
输入:8(2 5 6 9 10 2 7 4)预期输出:(2 7 9 9 12 5 7 6)实际输出:(2 7 9 9) 这是我的大学作业,也是我第一次在这里提问。我不知道为什么,但 10 没有扫描,有
$('div'); // 我在上面的代码中遇到错误。在检查 .js 代码时,我找不到名为 $ 的函数,但根据文档,应该有一个。 最佳答案 试试 http://ajax.googleapis.co
以下简单代码的输出对我来说有点奇怪。它错过了在控制台上打印的 0 到 100 之间的一些数字。 谁能解释一下为什么省略打印?我对并发编程完全陌生。 import java.util.concurren
我正在学习 xamarin 以构建移动应用程序,但我对 Xamarin 和移动应用程序一无所知。我打开了一个空白的移动应用程序,其中有“Hello world”示例并编辑了一些文本,但我的应用程序图标
我正在将一些值存储到 sqlite 数据库中。因此,数据是作为字符串从文本字段收集的,然后转换为 double 并持久化。 这是我试过的 NSDecimalNumber 答案; value.answe
我有一个奇怪的案例。突然,其中一个表中的一些记录(这么多记录)丢失了。首先,我认为这是由我的 PHP 脚本中的错误引起的。但是,我检查了一下,我的脚本中没有DELETE操作,只有UPDATE。有谁知道
我正在复制 NSString来自 NSDictionary进入本地NSString使用 [[NSString alloc] initWithString:] ,对其进行处理(删除一些字符),然后将其发
当保存在根文件夹中时,我的非常基本的 html 页面保持样式。为一个组创建了一个新文件夹,但是当我将页面移动到该文件夹时,它们似乎失去了与 css 文件的连接。 认为问题可能出在链接上,因为它现在
我需要使用 OpenCV 训练一些图像。但问题是,我找不到 opencv_createsamples 程序。我以正常方式安装了 OpenCV,因为我使用的是 Windows 7。这个 opencv_c
我有一个绑定(bind)到 JTable 的 ArrayList。之后 bindingGroup.unbind(); bindingGroup.bind(); (完成刷新数据)我丢失了表格单元格渲
所以基本上我们只是丢失了一个 keystore 和备份 keystore 。但是我们可能知道原始 keystore 的密码。 我的问题是,如果我们知道原始 keystore 的密码,我们可以重新生成
我是一名优秀的程序员,十分优秀!