argv 的重新分配
Reallocation of argv
我正在查看 GNU coreutils 包的代码,特别是 the program 'yes',当我在 main
函数(第 78 行)中看到这段代码时:
if (argc <= optind)
{
optind = argc;
argv[argc++] = bad_cast ("y");
}
数组argv
如何展开成这样?显然,只是将任何代码片段从上下文中取出是一个非常糟糕的主意,所以我事先查看了 argv
是否被修改了,除了在对 [=15= 的调用中似乎没有被修改过],它似乎不需要 "new size" 或类似的参数(但在 C 中,就像任何语言一样,事情并不总是它们看起来的那样)。
我决定编写一个简单的程序来测试我是否可以在 argv
上调用 realloc()
char** new_argv = realloc(argv, ++argc * sizeof*argv);
它有效(在 Windows 10 上使用 VS2013)。它返回一个指向已分配内存的指针。当然,如果它是未定义的行为,那实际上并不意味着 任何东西。
那么,长话短说,我的问题是,argv
是如何分配的?重新分配 argv
真的安全吗?
首先,argv[argc]
定义为NULL
。
其次,argc++
递增 argc
但 returns 它的旧值。
因此,argv[argc++] = ...
不会调用未定义的行为;它只是将一个新值分配给先前的 NULL
指针。
argv[argc++] = bad_cast ("y");
这不会扩展 argv
数组。它只是给 argv[argc]
赋值,然后递增 argc
。这确实打破了 argv[argc] == NULL
的初始保证,但只要代码不依赖于它是有效的。
标准保证:
The parameters argc
and argv
and the strings pointed to by the argv
array shall be modifiable by the program, and retain their last-stored
values between program startup and program termination.
它没有明确保证 argv
指向的数组中的 char*
指针是可修改的,但这是一个合理的假设。 (严格来说argv
指向数组的第一个元素,而不是数组本身,但是那句话已经够长了。)
char** new_argv = realloc(argv, ++argc * sizeof*argv);
这有未定义的行为。 realloc
的第一个参数必须是空指针或指向由 malloc
、calloc
、realloc
或等效项分配的内存的指针。 argv
指向的内存在输入 main
之前以某种未指定的方式分配。您可以复制数组,但不能合法地释放它,这是 realloc
所做的一部分。如果 realloc
调用对你来说表现得 "correctly",那你就太不走运了。 (如果你幸运,你的程序就会崩溃,这会告诉你有问题。)
我正在查看 GNU coreutils 包的代码,特别是 the program 'yes',当我在 main
函数(第 78 行)中看到这段代码时:
if (argc <= optind)
{
optind = argc;
argv[argc++] = bad_cast ("y");
}
数组argv
如何展开成这样?显然,只是将任何代码片段从上下文中取出是一个非常糟糕的主意,所以我事先查看了 argv
是否被修改了,除了在对 [=15= 的调用中似乎没有被修改过],它似乎不需要 "new size" 或类似的参数(但在 C 中,就像任何语言一样,事情并不总是它们看起来的那样)。
我决定编写一个简单的程序来测试我是否可以在 argv
realloc()
char** new_argv = realloc(argv, ++argc * sizeof*argv);
它有效(在 Windows 10 上使用 VS2013)。它返回一个指向已分配内存的指针。当然,如果它是未定义的行为,那实际上并不意味着 任何东西。
那么,长话短说,我的问题是,argv
是如何分配的?重新分配 argv
真的安全吗?
首先,argv[argc]
定义为NULL
。
其次,argc++
递增 argc
但 returns 它的旧值。
因此,argv[argc++] = ...
不会调用未定义的行为;它只是将一个新值分配给先前的 NULL
指针。
argv[argc++] = bad_cast ("y");
这不会扩展 argv
数组。它只是给 argv[argc]
赋值,然后递增 argc
。这确实打破了 argv[argc] == NULL
的初始保证,但只要代码不依赖于它是有效的。
标准保证:
The parameters
argc
andargv
and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
它没有明确保证 argv
指向的数组中的 char*
指针是可修改的,但这是一个合理的假设。 (严格来说argv
指向数组的第一个元素,而不是数组本身,但是那句话已经够长了。)
char** new_argv = realloc(argv, ++argc * sizeof*argv);
这有未定义的行为。 realloc
的第一个参数必须是空指针或指向由 malloc
、calloc
、realloc
或等效项分配的内存的指针。 argv
指向的内存在输入 main
之前以某种未指定的方式分配。您可以复制数组,但不能合法地释放它,这是 realloc
所做的一部分。如果 realloc
调用对你来说表现得 "correctly",那你就太不走运了。 (如果你幸运,你的程序就会崩溃,这会告诉你有问题。)