记忆移动制造一个地方垃圾
Memmove making one spot garbage?
我正在使用memmove
将std::string
元素向右移动一个位置。目的地的第一个地点是唯一一个被搞砸并充满垃圾的地方。我正在使用memmove
而不是strcpy
因为我在需要模板的类中使用它。不过,当我有一个整数数组时,它工作正常。关于如何为字符串解决此问题的任何想法?
/**
* @brief Shifts elements in the array to the right
* @param newItem The insert position.
*/
template<class T>
void DynamicArray<T>::shiftElementsRight(uint newItem) {
uint diff = _size - newItem;
memmove(&(_array[newItem + 1]),
&(_array[newItem]), sizeof(_array[0]) * diff);
}
我的主要
int main() {
DynamicArray<string> array(1);
string val1 = "val1";
array.add(val1);
string val2 = "val2";
array.add(val2);
// ... more additions ...
最后一个输出:
Sizeof: 8
Value is: val1
Value is: val11val3, val21
����[val1, val2A����[val1, val2, val31val4, Aq�����[val1, val2, val3 val4, val5Q`r�#����[val1, val2, val3, val4, val5, val61val5, 1val6, Q"����[val1, val2, val3, al4, a
8s��p�hp��p�hq�(r�Xr�KC�KC�KC�1val7, a:����[val1, val2, val3, val4, val5, qF����[val1, val2, val3, val4, val5, val6]
当数组包含std::string
对象时,memcpy
和memmove
都是不可能的。原因是两者都在不应该篡改对象内部时篡改(C++对象的完整性由其构造函数/赋值运算符/析构函数/成员函数确保,除非您确切知道自己在做什么,否则不得手动修改其字节)。
正如已经建议的那样,使用一种考虑构造函数、赋值运算符和析构函数的方法(例如std::copy_backward
),或者更好的是,摆脱那些遗留的 C 数组并使用适当的C++容器(如 vector
)并使用容器的函数插入/删除项目。
换句话说,一旦你开始使用C++对象,你就必须开始编写C++,而不是"带有类的C"。
来自memcpy描述:
为了避免溢出,数组的大小由两个 目标和源参数应至少为字节数,并且 不应该重叠(对于重叠的内存块,memmove更安全 方法)。
换句话说,使用memmove。
就像这里的大多数人说的那样,您可以使用memmove
而不是memcpy
因为它可以处理重叠的范围。
但是,C++解决方案是使用 copy_backward
,它明确执行您的要求,并将在屏幕后面为您选择最快的复制方法。那看起来像这样:
std::copy_backward(std::begin(_array)+newItem, std::end(_array)-1, std::end(array));
这意味着您将从上一个到最后一个元素向后复制以放置 newItem,并从后面开始插入该元素。这显然可以处理这需要的重叠。可能是在屏幕后面使用了memmove或其他特定于平台的内存副本。
SYNOPSIS
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
DESCRIPTION
The memcpy() function copies n bytes from memory area src to memory
area dest. The memory areas must not overlap. Use memmove(3) if the
memory areas do overlap.
您的内存区域不得重叠,否则不会定义memcpy
的行为。 您应该改用memmove
。
您不能将memcpy
用于重叠范围,如库文档中所述:
7.21.2 复制函数
7.21.2.1 内存函数
。
2 memcpy 函数将 n 个字符从 s2 指向的对象复制到 s1 指向的对象中。如果在重叠的对象之间进行复制,则行为是未定义的。
7.21.2.2 内存移动函数
。
2 memmove 函数将 s2 指向的对象中的 n 个字符复制到 S1 指向的对象。复制就像对象的 n 个字符一样发生 由 S2 指向的首先复制到一个由 n 个字符组成的临时数组中,该数组不 重叠 S1 和 S2 指向的对象,然后重叠 临时数组被复制到 S1 指向的对象中。
对于 POD 或简单初始化的类型,您可以使用 memmove
(如上所述)或std::copy_backward
(只要最后一个目标元素不在源范围内)
这个问题对memcpy-vs-memmove部分进行了更多讨论。
对于非平凡的类型,如std::string
,不能使用memcpy
或memmove
,而必须使用std::copy
或std::copy_backward
。
- 如何启用使用另一个类的静态方法的模板函数的自动推导,从而消除冗长的调用方代码
- 错误 C4716"当事方::运算符+":必须返回一个值
- 我在阅读一个简单的.txt时得到垃圾值
- 我遇到了一个关于多线程的小问题.需要多线程来计算 Pi 和方差
- 将一个结构分配给另一个结构会导致垃圾
- 数组的最后一个元素自动获取垃圾
- 记忆移动制造一个地方垃圾
- 正在初始化一个真正初始化的垃圾变量,或者只是一个赋值
- 动态分配数组中的某个值总是打印一个垃圾值
- 如果一个指定返回类型为int的函数没有任何返回语句,即不返回值,它会返回垃圾值吗
- 一个c++图形数据结构的并发垃圾收集
- 为什么c++中长度为n的字符串在[n]索引上总是有一个空字符作为垃圾?
- 将数据从调用方线程传递到另一个 boost::thread 中的方法
- 对于ifstream的每一行,ofstream到一个文件.垃圾保存在里面
- 输出一个整数数组以垃圾结束
- 在winsock中制作了一个c++套接字,并连接到谷歌,我在响应结束时得到了一些垃圾
- 访问存储在指针变量所指向的地址中的值(这是一个地址)返回垃圾值
- OpenCV只计算一个样本的协方差矩阵
- 一个c++协方差/覆盖/循环问题
- 当推送一个新对象时,指向该对象的指针将变成垃圾