内存在压入向量后被损坏
Memory is corrupted after pushing into the vector
为什么在压入vector后内存会损坏。在下面的程序中,我有一个带有字符串var的结构体(它不是指针)。我每次都创建一个局部结构对象,并分配一个字符串值并推到向量。在推到向量后,我正在对局部结构对象进行更改。但是这种变化反映在vector struct对象的字符串数据中。
#include <iostream>
#include <vector>
#include <string>
#include <memory.h>
using namespace std;
void PushVector(string);
struct thread_info
{
int id;
string threadname;
bool bval;
};
std::vector<thread_info> myvector;
int main ()
{
PushVector("Thread1"); // valid data into vector
PushVector("Thread2");
struct thread_info print;
while(!myvector.empty())
{
for(unsigned int index = 0; index < myvector.size(); ++index )
{
print = myvector.at(index);
cout<<"id : "<<print.id<<"nthread name : "<<print.threadname<<"nbool value : "<<print.bval<<endl;
}
myvector.clear();
}
return 0;
}
void PushVector(const string str)
{
std::cout << "Push the thread name to vectorn";
struct thread_info thread;
thread.id = 10;
thread.threadname = str;
thread.bval = true;
myvector.push_back (thread); //copying struct obj to vector
char* p = (char* )thread.threadname.c_str();
memcpy(p,"Wrong", 5); //==> Memory corrupting with invalid data after push back. Is it a limitation in C++?
thread.threadname = "blabla"; //trying to corrupt directly to string object
}
o/p:将线程名推入vector
将线程名推入vector
Id: 10
线程名:Wrongd1 ==>内存损坏?为什么没有绳子?
Bool值:1
Id: 10
线程名:Wrongd2 ==>内存损坏?为什么没有绳子?
Bool值:1
memcpy
到.c_str()
的结果是错误的。事实是,你不得不砍掉const
与cast不是一个暗示?是哪一种学习资源教会你这么做的?
正如paulm所说:
这样践踏字符串的内存只会导致眼泪。
std::string::c_str()
返回一个不能修改的常量缓冲区指针;由于某些工具链中存在某些优化(例如GCC <中的SSO;5.0)它甚至可能不是字符串真正的底层缓冲区,这似乎是你这里的情况。
忘记memcpy
;
在最好的情况下,您可以这样做:
thread.threadname.resize(5);
memcpy(&thread.threadname[0], "Wrong", 5);
或者,在c++代码中:
thread.threadname.resize(5);
std::copy("Wrong", "Wrong"+5, &thread.threadname[0]);
但是,如果是真的,你应该写:
thread.threadname = "Wrong";
tl;
您的memcpy()
在const
指针上(这是未定义的行为)与写时复制优化发生冲突。
是的,vector::push_back()
将对象的副本压入vector。在push_back()
修改了本地thread_info
对象之后,对本地对象的修改应该不会影响矢量中的对象,对吧?
std::string
允许假设对它的任何访问都将以一种定义良好的方式发生。对.c_str()
返回的(const
)指针执行memcpy()
是没有定义好的。
所以…假设std::string
在将thread_info
对象复制到vector中时采取了一种快捷方式:它没有复制所包含的数据,而是将指针复制到数据上,因此两个std::string
对象引用相同的内存区域。
它可以将复制延迟到实际需要的时候(如果),即当通过任何定义的函数(如string::insert()
或operator+=
)写入其中一个字符串时。这被称为"写时复制",一种相当常见的优化。
通过从.c_str()
的返回值中抛弃const
并在其上运行memcpy()
,你挫败了这一机制。因为您没有遍历任何可以执行写时复制的string
成员函数,所以这两个对象(应该是不同的)仍然指向相同的数据内存。
GDB输出,断点位于PushVector()
的最后一行:
(gdb) print &thread
$3 = (thread_info *) 0x7fffffffe240
(gdb) print &myvector[0]
$4 = (thread_info *) 0x605040
两个thread_info
对象不同。
(gdb) print &thread.threadname
$5 = (std::string *) 0x7fffffffe248
(gdb) print &myvector[0].threadname
$6 = (std::string *) 0x605048
两个string
对象也不同。
(gdb) print thread.threadname.c_str()
$7 = 0x605028 "Wrongd1"
(gdb) print myvector[0].threadname.c_str()
$8 = 0x605028 "Wrongd1"
但是它们指向同一个内存区域,因为两个string
对象都没有意识到有写访问,所以没有发生实际的数据复制。
- 为什么会发生堆损坏
- 写入向量<向量<bool>>
- 函数向量_指针有不同的原型,我可以构建一个吗
- std::向量与传递值的动态数组
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 将值指定给向量(2D)的向量中的某个位置
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 如何使用向量的template_back函数
- 尝试通过多个向量访问变量时,向量下标超出范围
- 使用全局声明的向量时,C++双重释放错误/损坏
- STL 向量无缘无故损坏,VC++ 2017
- 向量元素数据损坏了Find()操作
- 双重释放或损坏(输出):使用向量的组合算法0x0000000001a880a0***
- 在向量中使用不带复制且没有 noexcept 移动构造函数的对象.实际损坏的内容以及我如何确认它
- C 用向量序列化对象会导致双重自由损坏
- std::async - 参数向量已损坏
- CUDA - STL 向量在传递给使用 nvcc 编译的类时损坏
- 向量故障中的shared_ptr-迭代和丢失范围-获取损坏的数据
- 内存在压入向量后被损坏
- 从复制构造函数外部修改对象成员时导致向量内存损坏,但从复制构造函数内部修改时不会