C语言 资源的重新分配



我正在查看GNU coretils包的代码,特别是程序'yes',当我在main函数(第78行)中看到这段代码时:

if (argc <= optind)
{
  optind = argc;
  argv[argc++] = bad_cast ("y");
}

如何以这种方式扩展数组argv ?显然,只是把任何代码片段脱离上下文是一个非常坏的主意,所以我看了看argv是否事先被修改,它似乎不是除了在调用initialize_main (&argc, &argv),这似乎不需要一个参数为"新大小"或类似的东西(但在C中,像任何语言一样,事情并不总是他们似乎是)。

我决定写一个简单的程序来测试我是否可以在argv上调用realloc()

char** new_argv = realloc(argv, ++argc * sizeof*argv);

它工作(与Windows 10上的VS2013)。它返回一个指向已分配内存的指针。当然,这并不意味着任何,如果它是未定义的行为。

所以,长话短说,我的问题是,argv是如何分配的?realloc argv是否安全?

首先,将argv[argc]定义为NULL

第二,argc++增加argc,但返回原来的值。

因此,argv[argc++] = ...不会调用未定义行为;它只是给先前的NULL指针赋一个新值。

argv[argc++] = bad_cast ("y");

这不会扩展argv数组。它只是给argv[argc]赋值,然后增加argc的值。这确实打破了argv[argc] == NULL的初始保证,但只要代码不依赖于它是有效的。

标准保证:

形参 argc argv 以及argv数组可以被程序修改,并保留它们最后存储的值程序启动和程序终止之间的值。

没有明确保证argv所指向的数组中的char*指针是可修改的,但是可以合理地假设它们是可修改的。(严格来说,argv指向数组的第一个元素,而不是数组本身,但这句话已经足够长了。)

char** new_argv = realloc(argv, ++argc * sizeof*argv);

这有未定义的行为。realloc的第一个参数必须是空指针或指向由malloccallocrealloc或其他类似对象分配的内存的指针。在进入main之前,argv所指向的内存以某种未指定的方式分配。您可以复制数组,但不能合法地释放它,这是realloc所做的一部分。如果realloc调用对你来说表现"正确",你只是不走运。(如果你足够幸运的话,你的程序会崩溃,这会告诉你有问题。)

相关内容

  • 没有找到相关文章

最新更新