如何用更大的 char 指针列表覆盖 char 指针数组?
我的函数正在传递一个结构体,其中包含一个以 NULL 结尾的指针数组,这些指针指向组成带有参数的命令的单词。
我正在对参数列表执行全局匹配,将它们扩展为完整的文件列表,然后我想用新扩展的参数数组替换传递的参数数组。
通配工作正常,即 g.gl_pathv 填充了预期文件的列表。但是,我无法将此数组复制到给定的结构中。
#include <glob.h>
struct command {
char **argv;
// other fields...
}
void myFunction( struct command * cmd )
{
char **p = cmd->argv;
char* program = *p++; // save the program name (e.g 'ls', and increment to the first argument
glob_t g;
memset(&g, 0, sizeof(g));
g.gl_offs = 1;
int res = glob(*p++, GLOB_DOOFFS, NULL, &g);
glob_handle_res(res);
while (*p)
{
res = glob(*p, GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
glob_handle_res(res);
}
if( g.gl_pathc <= 0 )
{
globfree(&g);
}
cmd->argv = malloc((g.gl_pathc + g.gl_offs) * sizeof *cmd->argv);
if (cmd->argv == NULL) { sys_fatal_error("pattern_expand: malloc failed\n");}
// copy over the arguments
size_t i = g.gl_offs;
for (; i < g.gl_pathc + g.gl_offs; ++i)
cmd->argv[i] = strdup(g.gl_pathv[i]);
// insert the original program name
cmd->argv[0] = strdup(program);
** cmd->argv[g.gl_pathc + g.gl_offs] = 0; **
globfree(&g);
}
void
command_free(struct esh_command * cmd)
{
char ** p = cmd->argv;
while (*p) {
free(*p++); // Segfaults here, was it already freed?
}
free(cmd->argv);
free(cmd);
}
编辑1:另外,我意识到我需要将程序放回原处,如 cmd->argv[0]
编辑 2:添加了对 calloc 的调用
编辑 3:使用 Alok 的提示编辑内存管理
编辑 4:来自 alok 的更多提示
编辑5:几乎可以工作..应用程序在释放命令结构时出现段错误
最后:似乎我错过了终止NULL,所以添加行:
cmd->argv[g.gl_pathc + g.gl_offs] = 0;
似乎使它工作。
My function is being passed a struct containing, among other things, a NULL terminated array of pointers to words making up a command with arguments.
I'm performing a glob match on the list of arguments, to expand them into a full list of files, then I want to replace the passed argument array with the new expanded one.
The globbing is working fine, that is, g.gl_pathv is populated with the list of expected files. However, I am having trouble copying this array into the struct I was given.
#include <glob.h>
struct command {
char **argv;
// other fields...
}
void myFunction( struct command * cmd )
{
char **p = cmd->argv;
char* program = *p++; // save the program name (e.g 'ls', and increment to the first argument
glob_t g;
memset(&g, 0, sizeof(g));
g.gl_offs = 1;
int res = glob(*p++, GLOB_DOOFFS, NULL, &g);
glob_handle_res(res);
while (*p)
{
res = glob(*p, GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
glob_handle_res(res);
}
if( g.gl_pathc <= 0 )
{
globfree(&g);
}
cmd->argv = malloc((g.gl_pathc + g.gl_offs) * sizeof *cmd->argv);
if (cmd->argv == NULL) { sys_fatal_error("pattern_expand: malloc failed\n");}
// copy over the arguments
size_t i = g.gl_offs;
for (; i < g.gl_pathc + g.gl_offs; ++i)
cmd->argv[i] = strdup(g.gl_pathv[i]);
// insert the original program name
cmd->argv[0] = strdup(program);
** cmd->argv[g.gl_pathc + g.gl_offs] = 0; **
globfree(&g);
}
void
command_free(struct esh_command * cmd)
{
char ** p = cmd->argv;
while (*p) {
free(*p++); // Segfaults here, was it already freed?
}
free(cmd->argv);
free(cmd);
}
Edit 1: Also, I realized I need to stick program back in there as cmd->argv[0]
Edit 2: Added call to calloc
Edit 3: Edit mem management with tips from Alok
Edit 4: More tips from alok
Edit 5: Almost working.. the app segfaults when freeing the command struct
Finally: Seems like I was missing the terminating NULL, so adding the line:
cmd->argv[g.gl_pathc + g.gl_offs] = 0;
seemed to make it work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
argv
是char *
的指针数组。这意味着argv
有空间容纳argc
char *
值。如果您尝试将多个char *
值复制到其中,最终会出现溢出。您的
glob
调用很可能会在gl_pathv
字段中产生多个argc
元素(即gl_pathc > argc
) 。这是未定义的行为。它类似于下面的代码:
解决方案:您应该直接使用
glob_t
结构,或者分配新空间以将gl_pathv
复制到新的char **
:编辑:编辑后:
它应该可以工作,但是每个
argv[1]
到argv[g.gl_pathc + g.gl_offs - 1]
是一个char *
,由struct glob
“拥有”。您的memcpy
调用仅复制指针。当您稍后执行globfree()
时,这些指针不再具有任何意义。因此,您需要复制字符串供您使用:这可以确保您现在拥有自己的字符串私有副本。完成后请务必释放它们(和
argv
)。您的代码还存在一些其他问题。
*p++
,您应该执行p++
,因为您没有使用取消引用的值。glob
的返回值。paths
变量需要g.gl_pathc + 1
元素,而不是g.gl_pathc
。 (或者更正确地说,您需要分配g.gl_pathc + g.gl_offs
倍sizeof *paths
字节。)for
循环应为 (j=1; j < g.gl_pathc + g.gl_offs; ++j)。./a.out '*'
而不是./a.out *
。argv
is an array of pointers ofchar *
. This means thatargv
has space forargc
char *
values. If you try to copy more than that manychar *
values into it, you will end up with an overflow.Most likely your
glob
call results in more thanargc
elements ingl_pathv
field (i.e,gl_pathc > argc
). This is undefined behavior.It is similar to the code below:
Solution: you should either work with the
glob_t
struct directly, or allocate new space to copygl_pathv
to a newchar **
:Edit: after your edit:
it should work, but each of
argv[1]
toargv[g.gl_pathc + g.gl_offs - 1]
is achar *
that is "owned" by thestruct glob
. Yourmemcpy
call is only copying the pointers. When you later doglobfree()
, those pointers don't mean anything anymore. So, you need to do copy the strings for your use:This makes sure you now have your own private copies of the strings. Be sure to free them (and
argv
) once you are done.There are a few other problems with your code.
*p++
, you should dop++
, since you're not using the value of the dereferencing.glob
.paths
variable needsg.gl_pathc + 1
elements, notg.gl_pathc
. (Or more correctly, you need to allocateg.gl_pathc + g.gl_offs
timessizeof *paths
bytes.)for
loop to copy strings should befor (j=1; j < g.gl_pathc + g.gl_offs; ++j)
../a.out '*'
instead of./a.out *
.您不需要将 g.gl_pathc 乘以 sizeof(char *) 吗?
Don't you need to multiple g.gl_pathc by sizeof(char *)?