【问题标题】:How much memory is allocated for argv[]? [duplicate]为 argv[] 分配了多少内存? [复制]
【发布时间】:2017-01-30 07:15:22
【问题描述】:

我知道命令行参数是字符数组,它们存储在堆栈中。但我想知道为每个参数分配的实际内存。例如假设我将目录名称“/tmp”作为命令行参数传递。这将存储在 argv[1] 中。但正如我测试的那样,允许在程序中将 argv[1] 更改为“/tmp/log/”(大小增加)。这怎么可能?

【问题讨论】:

  • “我知道”之后是未经证实的猜测。
  • "但是我测试过,允许在程序中将 argv[1] 更改为 "/tmp/log/"(大小增加)。"是的,C 标准允许您修改 argv 指向的字符串(N1570,第 5.1.2.2.1 节,第 2 节,最后一个约束),但“增加它们的大小”可能是 UB。您应该假设可修改的char[] 与以零结尾的字符串一样多。
  • 如果您argv[1] = "/tmp/log"),您并没有增加argv[1] 指向的字符串的大小,而是用另一个指针替换了一个指针。我怀疑strcat(argv[1], "/log") 是否会成功。
  • @techiek7 那会覆盖字符串,所以如果输入比原来的参数长,就会是UB。
  • 我知道 SO 真的很喜欢给人们投反对票,但鉴于指定了一个平台,并且该平台是开源的,这个问题有一个可验证的答案。

标签: c++ linux command-line-arguments


【解决方案1】:

在 Linux 上,参数由 create_elf_tables 填充。至少对于这个特定平台,您将值存储在堆栈中是正确的。

Linux 仅使用在堆栈上存储参数和(初始)环境变量所需的内存;如果您尝试使用的内容超出现有内容,您将覆盖其他内容(或崩溃)。

【讨论】:

    【解决方案2】:

    标准规定 argv 是可以修改的,因为它是一个特殊的内部。

    177 — 参数 argc 和 argv 以及 argv 数组指向的字符串应该可以被程序修改,并在程序启动和程序终止之间保留它们最后存储的值,所以它只分配你需要的分配或替换。

    标准文本: http://c0x.coding-guidelines.com/5.1.2.2.1.html

    【讨论】:

    • 请注意,您引用了 proposed C 标准。
    【解决方案3】:

    要回答您的问题,可通过以下方式获得参数字符串和传递的环境的最大总大小:

    getconf ARG_MAX
    

    来自命令行或来自 C 的 syconf 等效项(有关更多信息,请参阅http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html)。 (在我的 Linux 机器上,限制是 2097152)。

    您的示例恰好有效,因为参数和环境实际上是连续存储的,因此附加到字符串将覆盖其后面的内容(后面的参数或环境)。 这就是为什么尝试像这样扩展 argv 字符串是个坏主意。如果你想修改它们,要么编辑它们,要么缩小它们,但试图扩展它们是个麻烦事。

    【讨论】:

    • 这很好地回答了它。此外,我尝试在 argv[0][0] 的起始地址后打印 100 个字符。参数和环境实际上是连续存储的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 2017-05-18
    • 1970-01-01
    相关资源
    最近更新 更多