未定义行为 std::vector

huangapple go评论44阅读模式
英文:

undefined behavior std::vector

问题

这段代码是否属于未定义行为?看起来似乎没有动态分配内存,所以我想知道程序如何处理项目的赋值。我使用的是OSX Monterrey,它打印出"10",看起来是"符合预期的"。

英文:
#include <iostream>
#include <string>
#include <vector>

int main()
{
  std::string name;
  std::vector<double> v(5, 1);
  std::cout<<v.capacity()<<std::endl;
  v[1000000]= 10.;
  std::cout<<v[1000000]<<std::endl;
  std::cout<<v.capacity()<<std::endl;
  return 0;
}

Is this code undefined behavior ? It seems that no allocation is made on the fly so I am wondering how the program is able to handle the item assignment. I am using OSX Monterrey and this prints "10" as "expected".

答案1

得分: 0

  std::vector<double> v(5, 1);
  std::cout << v.capacity() << std::endl;
  v[1000000] = 10.;

从你的问题中,我非常确定你知道这是未定义行为。你的问题实际上是:“为什么这不崩溃?”

未定义行为意味着任何事情都可能发生。通常情况下,应用程序似乎可以正常工作。向量将向std::allocate请求约20字节的内存,然后std::allocate将向操作系统请求大块内存,然后将20字节的内存分配给向量,然后将大块内存的剩余部分保留给下一个请求更多内存的对象。然后,您的代码将10赋值给(虚拟)内存中距向量分配的内存约4MB的位置。

从那里,有一个可能性,即内存中的该地址在您的进程中尚未分配。操作系统将检测到这一点,通常会导致应用程序崩溃。或者它可能会将该内存分配给您的应用程序,以使其继续运行。因此,您永远无法真正知道会发生什么。

另一个选项是,如果内存中的该地址恰好已经由std::allocate或其他某些对象巧合地分配给您的进程,那么写入将成功写入10到内存中的那个位置。希望那不是重要的内容,比如网络代码,否则下一个网络调用可能会发送您的内存内容,包括密码,到该时正在与其通信的服务器。或者也许这段内存当前没有用于任何事情,什么都没有破坏。或者也许它在连续998次工作正常,然后在第999次时删除了您的文件。这很不太可能,但有可能。

所以是的,大多数时候"未定义行为仍然能正常工作"。但不要这样做,您后悔的。

英文:
  std::vector&lt;double&gt; v(5, 1);
  std::cout&lt;&lt;v.capacity()&lt;&lt;std::endl;
  v[1000000]= 10.;

From your question, I'm pretty sure you know this is undefined behavior. Your question is really "why doesn't this crash?"

Undefined behavior means anything can happen. Usually what happens is the app seems to work. The vector will ask std::allocate for ~20 bytes of memory, and std::allocate will ask the operating system for a large chunk of memory, and then std::allocate will give 20 bytes of memory to the vector, and then it will save the rest of the large chunk for whatever next asks for more memory. Then your code assigns 10 to the place in (virtual) memory that's ~4MB past the memory allocated to the vector.

One possibility from there, is that that address in memory is not currently allocated in your process. The OS will detect this and usually it will crash your app. Or it might just give that memory to your app so that it keeps running. So you never really know what will happen.

Another option is that If that address in memory happens to already be allocated in your process, either coincidentally by std::allocate, or coincidentally by something else, then the write succeeds in writing 10 to that place in memory. Hopefully that wasn't important, like networking code, in which case the next network call could send the contents of your memory, including your passwords, to whatever server it happened to be talking to at the time. Or maybe that memory isn't currently used for anything at the moment, and nothing breaks. Or maybe it works a 998 times in a row, and then on the 999th time it erases your files. Unlikely, but possible.

So yes, most of the time "undefined behavior works anyway". But don't do it, you will regret it.

huangapple
  • 本文由 发表于 2023年2月7日 03:59:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75366001.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定