矢量的C++读取访问冲突
C++ Read access violation for vector
当我尝试使用vector[int_number]并且我的程序停止工作时,我得到了一个异常。
uint64_t data = 0xffeeddccbbaa5577;
uint16_t *vector = (uint16_t*) data;
int currentPosition = 0;
while (currentPosition <= 3) {
uint16_t header = vector[currentPosition]; // problem here
Visual Studio 2017返回我:引发未处理的异常:读取访问冲突。矢量为0x6111F12。
我被困在这里了。如果你知道我该怎么做,我将不胜感激。提前感谢!
抛开由于严格混叠违规而导致的所有未定义行为不谈,在当前的英特尔芯片和MSVC运行时中,所有指针都是48位。
因此0xffeeddccbbaa5577
是,而不是有效的指针值。
因此,取消引用该值的行为将是未定义的。
如果您想将data
分解为四个适当类型的元素,那么一种方法是创建一个uint16_t foo[4]
,比如说memcpy
,即从&data
到foo
开始的数据。
通过投射获得的不同类型的指针访问数据,您将进入未定义的行为领域。相反,请尝试以下操作(注意,我还将while循环替换为ranged for循环,以避免必须保留计数器)
#include <iostream>
#include <cstring>
int main() {
uint64_t data = 0xffeeddccbbaa5577;
uint16_t vector[4];
memcpy(vector, &data, sizeof(uint64_t));
for (uint16_t header : vector)
{
std::cout << std::hex << header << std::endl;
}
}
产生
5577
bbaa
ddcc
ffee
若您使用reinterpret_cast
,您持有指向同一地址的两个不同类型的指针,这可能很容易导致未定义的行为。memcpy
通过创建内存位置的副本来避免这种情况,并且您可以使用不同类型的指针安全地访问它。也可以看看类型双关语(如@DanielLangr所指出的)
这真的很容易,但你与最初的尝试相去甚远,以至于让所有人都感到困惑。
uint16_t vector[] = { 0x5577, 0xbbaa, 0xddcc, 0xffee };
问正确的问题,如果你在评论中问了你的问题,我们会更快地到达那里。
这里有一个具体的例子,应该可以避免由于严格的别名/"非法"强制转换等而导致的任何未定义的行为,因为这似乎是你真正感兴趣的。
此代码获取一个std::uint64_t
,将其复制到由四个std::uint16_t
组成的数组中,修改数组中的值,然后将它们复制回原始std::uint64_t
。
#include <cstdint>
#include <cstring>
#include <iostream>
int main() {
std::uint64_t data = 0xffeeddccbbaa5577;
std::uint16_t data_spliced[4];
std::memcpy(&data_spliced, &data, sizeof(data));
std::cout << "Original data:n" << data << "nOriginal, spliced data:n";
for (const auto spliced_value : data_spliced) {
std::cout << spliced_value << " ";
}
std::cout << "nn";
data_spliced[2] = 0xd00d;
memcpy(&data, &data_spliced, sizeof(data));
std::cout << "Modified data:n" << data << "nModified, spliced data:n";
for (const auto spliced_value : data_spliced) {
std::cout << spliced_value << " ";
}
std::cout << 'n';
}
输出(在我的机器上):
Original data:
18441921395520329079
Original, spliced data:
21879 48042 56780 65518
Modified data:
18441906281530414455
Modified, spliced data:
21879 48042 53261 65518
如果要将该变量分配给指针,则需要获取该变量的地址
const uint16_t* vector = reinterpret_cast<const uint16_t*>( &data ) ;
注意:这适用于MSVC 2017,但是。。。
这是一辆行为不明的卡车!–巴斯谢巴
正如reinterpret_cast
的cpreference所说:
5)指向类型
T1
的对象的任何指针都可以转换为指向另一类型cv T2
的对象的指针。这完全等同于static_cast<cv T2*>(static_cast<cv void*>(expression))
(这意味着如果T2
的对齐要求不比T1
的更严格,则指针的值不会改变,并且将结果指针转换回其原始类型会产生原始值)。在任何情况下,只有在类型别名规则(见下文)允许的情况下,才能安全地取消对结果指针的引用键入别名。每当试图通过AliasedType类型的glvalue读取或修改DynamicType类型对象的存储值时,除非以下情况之一为真,否则行为是未定义的:
- AliasedType和DynamicType相似
- AliasedType是(可能是cv限定的)DynamicType的有符号或无符号变体
- AliasedType是std::byte(从C++17开始)、char或unsigned char:this允许检查任何对象的对象表示字节数组
注意,许多C++编译器将此规则作为非标准语言扩展放宽,以允许通过联合的非活动成员进行错误类型的访问(这种访问在C中没有定义)
上述代码不满足任何别名规则。
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 读取访问冲突.这0xCDCDCDCD
- 尝试通过共享指针使用变量时读取访问冲突
- C++ 读取访问冲突,0xCDCDCDCD
- 从二进制文件中读取元素时引发异常(引发异常:读取访问冲突. _Pnext 0xB414D4)
- 使用智能指针读取访问冲突
- 引发异常:读取访问冲突.**此**0x40错误
- 函数 AfxEndThread 中的读取访问冲突"pThread-> was nullptr"
- Visual Studio图形调试器引发读取访问冲突异常
- C++中的内存分配(引发异常:读取访问冲突)
- 引发异常:读取访问冲突 [C++]
- 尝试从单向链表C++中删除单个节点时出现读取访问冲突
- 引发未经处理的异常:简单 C++ 程序中的读取访问冲突,动态增加数组长度以存储数字
- 错误 : 异常 : 引发未处理的异常: 读取访问冲突.0xDDDDDDDD临时温度
- 读取访问冲突. _Mycont 在 C++ 中将 udp 数据放入向量时出现 nullptr 错误
- 读取访问冲突0xCDCDCDCD
- Vector::p ush_back() 给出读取访问冲突
- 访问共享内存时出现读取访问冲突
- 挂钩创建文件抛出异常:读取访问冲突
- 不能对基于数组的指针使用数组运算符(读取访问冲突)