我不明白附加字符串的内存问题

I don't understand about memory issue of appending string

本文关键字:内存 问题 字符串 明白      更新时间:2023-10-16

运行时错误:基本0x000000000000的指针索引表达式溢出到0xffffffffffffffffffff for频率排序

在该链接的第一个答案中,它说将char附加到字符串会导致内存问题。

string s = "";
char c = 'a';
int max = INT_MAX;
for(int j=0;j<max;j++)
    s = s + c;

答案解释了[上面代码中的s=s+c一次又一次地复制了相同的字符串,因此会引起内存问题。]但是我不明白为什么该代码一次又一次地复制相同的字符串。

是否有人可能让我理解那部分:(?

我不明白为什么该代码再次复制相同的字符串,并且 再次。

好吧,让我们看一下每次迭代时都会发生什么:

s = s + c;

程序要执行该行要执行三件事:

  1. 计算临时值s + c-为此,该程序必须创建一个临时的匿名std::string对象,并为其分配(从堆中(一个内部字节缓冲器,它至少是一个字节更大的字节比当前s中的字符数(以便可以容纳s的所有旧内容,加上c提供的其他字符(

  2. 设置s等于临时弦。在C 03和更早的时间里,这将通过重新定位s的内部字节屏障来更大,然后将所有字节从临时弦乐中复制到s的新/较大缓冲区中。C 11通过新的Move-Assignment运算符对此进行了一些优化,因此不必复制所有字节。相反,s可以简单地占据临时弦的字节 - 逃避者。

  3. 现在我们已经完成了临时字符串的资源。实际上,这采用std::string类的destuructor的形式,在旧的(无较长的大型(字节击败上调用delete[]

鉴于以上将在循环中至少执行20亿次,因此它已经效率很低。

但是,我认为您提到的答案特别关注的是堆分裂。请记住,堆分配不起作用。当您(或std::string类或任何人(要求从堆分配内存的n字节时,Heap实现的作业是找到 contiguul 内存的n个字节并将其返回。而且,由于C 没有任何规定用于移动内存块(因为这样做会使程序可能指向那些内存块的任何指针无效(,因此堆无法创建N Byte连续chunk从较小的块中;相反,必须有一系列连续的内存空间。例如,如果1GB的内存由数千个非连续的1KB块组成,并且呼叫者要求分配2KB。

因此,堆的工作是有效地分配了对程序请求的大小的大小记忆,当它们再次释放时,它将尝试将它们再次粘合到更大的块中,但可能并不总是总是能够。分配和释放内存的某些模式可能会导致 heap碎片,这只是大量不连续的内存分配,这些分配使它们之间的自由存储器之间的很小的自由记忆区域无法使用。

我不确定这种特定的分配/自由模式是否会导致。鉴于一次只分配了一个或两个缓冲区,因此堆可能能够重新吸收它们重新释放到相邻的自由记忆块中 - 这可能取决于系统正在使用的特定堆算法,例如以及是否有其他线程在此过程中分配/释放堆内存。但是,如果有系统会引起问题的系统(尤其是在虚拟地址空间有限的16位或32位系统上,或者不使用虚拟内存的嵌入式系统(,我不会感到惊讶(