gpt4 book ai didi

C 代码神秘地改变结构的值(有趣的神秘代码行为)

转载 作者:太空宇宙 更新时间:2023-11-04 02:44:33 27 4
gpt4 key购买 nike

我正在为一个示例 UNIX shell 在 C 中实现历史功能。我创建了一个名为 History 的结构数组,其中每个结构元素包含一个整数(历史编号)和命令(一个字符串数组,每个字符串作为命令的参数)。重要部分用***表示。

struct HistoryElement
{
int NumberOfCommandGiven;
char * command[MAXLINE/2+1];
};

int main(void)
{
char iBuffer[MAXLINE];
char *args[MAXLINE/2+1];
int bgrnd;
int numberofcommand = 0; //The most recent number given to a command entered (for history).
int currentposition;
int historysize = 12;
struct HistoryElement* History = malloc(historysize*sizeof(struct HistoryElement)); //Create an array of HistoryElements.
struct HistoryElement blank = { -1, "NothingHere" };
int j=0;
//clear out any garbage contents of the history and replace with placeholder element called blank.
for(j=0;j<historysize;j++) {
History[j]=blank;
}

while (1) {
bgrnd = 0;
printf("IansSh: ");
fflush(0);
setup(iBuffer, args, &bgrnd);

//Test that the entry was stored correctly -- This outputs "ls" before calling history, but after calling history is outputs "history". How did History[0] get changed???
printf("History[0].command equals %s \n",History[0].command[0]);

if(strcmp(args[0],"history")==0 || strcmp(args[0],"h")==0) { //***
//WHY is this section rewriting my array of structs?
int i;
for(i=0;i<historysize;i++) {
if(History[i].NumberOfCommandGiven!=-1)
{
if(History[i].NumberOfCommandGiven!=0) {
printf("%d : %s \n",History[i].NumberOfCommandGiven, History[i].command[0]);
}
else {
printf("%d : Command was removed due to a more recent command of the same entry. \n", History[i].NumberOfCommandGiven);
}
}
}
}
//***
else {
printf("Got into final else");
pid_t errorchecker;
errorchecker = fork(); //Create child process
numberofcommand++;
//Add the command to history: ***
struct HistoryElement input;
input.NumberOfCommandGiven = numberofcommand;
memcpy(input.command, args, sizeof(args));
History[numberofcommand-1%historysize] = input;
//Remove any old entries of that exact command from the history, if they exist:
int k =0;
for(k=0;k<historysize;k++)
{
if(History[k].command==input.command && History[k].NumberOfCommandGiven!=numberofcommand)
{
History[k].NumberOfCommandGiven=0;
}
}
if(errorchecker < 0) {
printf("An error occurred when trying to fork a child process.");
continue;
}
else if(errorchecker==0) {
//Execute the command, of course:
execvp(args[0],args);
// Print the error if an error occurred.
char* err = strerror(err);
printf("IansSh error occurred (You most likely entered an invalid command): %s: %s\n", args[0], err);
}
if(bgrnd==0) {
//if specified (ie. an '&' was not included), wait on child process to finish before continuing.
int child;
waitpid(errorchecker, &child, 0);
}
}
}
free(History);
}

在我的代码中,有一个部分专门用于调用命令“history”。这当然不是要将自己作为命令实际添加到历史记录中,而是要逐行显示历史记录。但是,出于某种原因,这部分代码正在重写我的结构数组的值,将每个命令的条目更改为简单的“历史记录”。因此,当我进行测试时,我会得到如下信息:

ls -l
(successfully outputs results of ls -l)
ls
(successfully outputs results of ls)
history
1 : history
2 : history

相反,1 和 2 应分别对应于“ls -l”和“ls”,就像它们存储在 main 的结构中一样。

最佳答案

在这里,您正在创建一个结构,其中第二个字段是 char *[]

struct HistoryElement input;
input.NumberOfCommandGiven = numberofcommand;
memcpy(input.command, args, sizeof(args));
History[numberofcommand-1%historysize] = input;

编辑:首先,正如@MattMcNabb 指出的那样,注意你的优先顺序!numberofcommand-1%historysize 被评估为 numberofcommand-(1%historysize) 这将导致注销数组的末尾(并且可能是段错误)。

memcpy 复制args 中的指针,但不为args 中的实际字符串分配和复制内存。为此,您需要遍历 args(而不是 memcpy)并使用 strdup 创建字符串的新副本。

int i;
for (i = 0; args[i] != NULL; ++i) {
input.command[i] = strdup(args[i]);
if (input.command[i] == NULL) {
/* handle allocation error */
}
}
input.command[i] = NULL;

稍后您还需要释放所有这些字符串,因此您不应再在不释放结构已分配的任何可能指针的情况下覆盖它。

struct HistoryElement old = History[(numberofcommand-1)%historysize];
int i;
for (i = 0; old.command[i] != NULL; ++i) {
free(old.command[i]);
old.command[i] = NULL;
}
History[(numberofcommand - 1) % historysize] = input;

但是初始的 blank 是如何适应这个的呢?我们无法释放“NothingHere”,而且无论如何初始化都被破坏了:

struct HistoryElement blank = { -1, {NULL} };

关于C 代码神秘地改变结构的值(有趣的神秘代码行为),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28687033/

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