有人可以向我解释为啥这是可能的吗? [复制]

Posted

技术标签:

【中文标题】有人可以向我解释为啥这是可能的吗? [复制]【英文标题】:Can someone explain to me why this is possible? [duplicate]有人可以向我解释为什么这是可能的吗? [复制] 【发布时间】:2022-01-22 14:47:45 【问题描述】:
int main ()

   char *strA = "abc";
   int tam_strA = strlen(strA);
   
   char strB[tam_strA];
   strB[0] = 'a';
   strB[1] = 'b';
   strB[2] = 'c';
   strB[3] = 'd';
   strB[9] = 'z';
   
   printf("%c", strB[9]);
   
   return 0;

它正常打印'z'。为什么它不返回分段错误错误?因为我试图访问一个不应该存在的索引,因为 strB 的大小(索引数量)等于 tam_strA 等于 3。

另外,改用char strB[strlen(strA)]; 有什么不同/问题吗?

【问题讨论】:

意外行为意味着任何事情都可能发生。您的代码演示了一种可能的行为;还有无数其他的。如果您通过strA 打印,您可能会遇到崩溃。 如果strB[9] 位于不属于您的内存中,并且硬件配置为导致系统故障,则会发生这种情况。但是,如果strB[9] 在您拥有的内存中,则除非存在使用该内存位置的竞争,否则不会引起问题。如果您不干扰任何其他用途(反之亦然),就不会有问题。假设您去剧院并坐在您没有预订的座位上。如果没有其他人愿意使用同一个座位,您可能会喜欢整个节目,否则会有麻烦。 What is undefined behavior and how does it work? C 不能保护您免于射中自己的脚(这样做时称为未定义行为)。 C 不为您检查所有内容背后的想法是,您可以在需要时检查自己......当您不需要时,您编译的程序被设计简化。 请选择一个标题,该标题提供有关您的问题的信息,而不是笼统的陈述。谢谢。 【参考方案1】:

C 语言没有阻止您访问无效内存的规范,也不保证会出现分段错误。唯一的承诺是,如果您尝试访问无效内存,则会导致undefined behavior。

分段错误是可能的结果之一,而不是唯一的。

也就是说,唯一的问题是

 char strB[strlen(strA)];

就是,strB 的长度不足以容纳strA 中的内容,因为它将缺少一个字节来保存空终止符。当然,按字节使用会很好,但如果你想复制内容(或与strA 相同长度的任何内容)并将strB 用作字符串,你将跑过分配的内存(在没有空终止符的情况下),调用未定义的行为。

【讨论】:

【参考方案2】:

只有在访问不属于您的内存时才会出现分段错误。你拥有你的整个堆栈。 strB[9] 在操作系统看来是一个有效的内存访问。您不应该这样做的原因是因为编译器不知道您正在使用该内存,因此它可能决定将该内存用于其他用途。它还有助于提高可读性并最大限度地减少程序员的错误。而且,该标准将使用未声明的内存定义为未定义的行为,因此您不能安全地使用它。声明像int x;(或数组)这样的变量会告诉编译器您将使用x 处的内存。

这其实和这个问题有关:Why does the first element outside of a defined array default to zero?。阅读那里更详细的答案。

【讨论】:

"你拥有你的整个堆栈" 这并不完全正确,请参阅 en.wikipedia.org/wiki/Stack_buffer_overflow。此外,计算机上不一定有运行 C 程序的操作系统。 @Lundin 在编译器和操作系统的视图中内存所有权之间存在差异。由于操作系统导致分段错误,我正在谈论这个。您是否正确阅读了我的答案? SIGSEGV 被定义为(C17 7.14)“对存储的无效访问”。 *nix-like 操作系统以某种方式处理它,但这只是操作系统特定的行为。 @Ludin 整个堆栈都是对内存的有效访问,除非我们采用一个不起眼的平台或另一个宇宙。访问无效的堆栈内存将永远是“未定义的行为”。 @Lundin 如果没有操作系统,就没有内存管理,因此没有无效的内存访问。你的观点对我来说毫无意义。您正在尝试使用“无效的内存访问”的确切含义,但隐含地表明我没有使用确切的含义。 "strB[9] 行是操作系统眼中的有效内存访问。您不应该这样做的原因是因为编译器不知道您正在使用该内存,因此它可能决定使用那个记忆用于其他用途。”似乎一切都清楚了。我只是不明白你。

以上是关于有人可以向我解释为啥这是可能的吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

有人可以向我解释为啥 L(长)必须在那里吗? [复制]

返回新字符串(密码);有人可以解释一下,这是如何返回 String 的吗? [复制]

有人可以解释 C++ FAILED 函数吗?

有人可以向我解释为啥完美平方是 O(sqrt(n)) 的运行时间吗?

这是 WordPress 中的 .htaccess 代码。有人可以解释它是如何工作的吗?

有人可以解释这些 apache bench 结果吗,有啥突出的吗?