std::copy无一例外导致错误
std::copy causes error without exception
我有这段代码可以复制一个整数:
int parseInt(const char* data, unsigned int* ind) {
int i;
std::copy(&data[*ind], &data[*ind+sizeof(int)], &i); // i) STD::COPY
// memcpy(&i, &data[*ind], sizeof(int)); // ii) MEMCPY
std::cout << "--> " << i << std::endl;
*ind += sizeof(int);
std::cout << "OK" << std::endl;
return i;
}
在 debian
上,此代码 有效 i) STD::COPY.
然后,我编译了 运行 embedded Arm 上的代码(sizeof(int)
也是 4)。 i) 的代码似乎也是 运行ning,在函数内打印预期的内容。
但是,从函数返回时会导致问题。
我也试过 return 1;
而不是 i
,但是一样。它不抛出异常,不提供任何线索。我无法调试,因为我有限制,无法添加调试器。
只是在这个函数之后没有继续,即:
std::cout << "PARSING..." << std::endl;
parseInt(data, &ind);
std::cout << "PARSED!" << std::endl;
...
给出这个(值 11 是正确的):
PARSING...
--> 11
OK
然后进程冻结。
但是,当我使用 ii) MEMCPY 而不是 std::copy
时,代码有效。因此,这个问题在我看来似乎是因为 std::copy
.
有人知道这里会发生什么吗?
我用错了std::copy
吗?但是为什么它可以在 debian 桌面上运行,而不能在 arm embedded 上运行呢?
std::copy(&data[*ind], &data[*ind+sizeof(int)], &i);
这会将 sizeof(int)
个字节复制到从 &i
开始的 int
数组的连续元素,不用说这会导致未定义的行为,因为 &i
处没有数组.
你的意思可能是
std::copy(&data[*ind], &data[*ind+sizeof(int)], reinterpret_cast<char*>(&i));
memcpy
工作的原因是因为它明确地复制字节,std::copy
更通用,就像它在抽象迭代器上运行的其他标准算法一样,由你来确保你调用它正确。
您的 ARM CPU 可能不支持未对齐的内存访问。 memcpy
会为您处理这种情况。
std::copy 的文档:
template <class InputIterator, class OutputIterator> OutputIterator
copy (InputIterator first, InputIterator last, OutputIterator result);
Copy range of elements Copies the elements in the range [first,last)
into the range beginning at result.
您正在使用类型为 const char* 的输入迭代器。输出迭代器的类型为 int*.
复制函数从头到尾迭代,导致 4 次迭代。每次迭代在输入中每次前进一个字节。但是输出迭代器是 int* 类型的,所以每次迭代输出迭代器前进 4 个字节。这导致您的 4 个输入字节被复制,每个字节之间有 3 个字节的分隔。
由于要接收该数据的元素是变量 i,它只能保存一个 int(4 字节),这会导致未定义的行为,表现为在未指定的内存位置写入。最有可能将 RET 指令所需的方向覆盖为 return 从相应的 CALL。
在 debian 中不会发生这样的事情取决于那里编译器的内存模型。你不能相信它是一致的。
在仍然使用 std::copy 的同时解决它的一种方法是使用 char* 迭代器作为输出迭代器:
char* ptrDest = reinterpret_cast<char*>(&i);
std::copy(&data[*ind], &data[*ind+sizeof(int)], ptrDest); // i) STD::COPY
我有这段代码可以复制一个整数:
int parseInt(const char* data, unsigned int* ind) {
int i;
std::copy(&data[*ind], &data[*ind+sizeof(int)], &i); // i) STD::COPY
// memcpy(&i, &data[*ind], sizeof(int)); // ii) MEMCPY
std::cout << "--> " << i << std::endl;
*ind += sizeof(int);
std::cout << "OK" << std::endl;
return i;
}
在 debian
上,此代码 有效 i) STD::COPY.
然后,我编译了 运行 embedded Arm 上的代码(sizeof(int)
也是 4)。 i) 的代码似乎也是 运行ning,在函数内打印预期的内容。
但是,从函数返回时会导致问题。
我也试过 return 1;
而不是 i
,但是一样。它不抛出异常,不提供任何线索。我无法调试,因为我有限制,无法添加调试器。
只是在这个函数之后没有继续,即:
std::cout << "PARSING..." << std::endl;
parseInt(data, &ind);
std::cout << "PARSED!" << std::endl;
...
给出这个(值 11 是正确的):
PARSING...
--> 11
OK
然后进程冻结。
但是,当我使用 ii) MEMCPY 而不是 std::copy
时,代码有效。因此,这个问题在我看来似乎是因为 std::copy
.
有人知道这里会发生什么吗?
我用错了std::copy
吗?但是为什么它可以在 debian 桌面上运行,而不能在 arm embedded 上运行呢?
std::copy(&data[*ind], &data[*ind+sizeof(int)], &i);
这会将 sizeof(int)
个字节复制到从 &i
开始的 int
数组的连续元素,不用说这会导致未定义的行为,因为 &i
处没有数组.
你的意思可能是
std::copy(&data[*ind], &data[*ind+sizeof(int)], reinterpret_cast<char*>(&i));
memcpy
工作的原因是因为它明确地复制字节,std::copy
更通用,就像它在抽象迭代器上运行的其他标准算法一样,由你来确保你调用它正确。
您的 ARM CPU 可能不支持未对齐的内存访问。 memcpy
会为您处理这种情况。
std::copy 的文档:
template <class InputIterator, class OutputIterator> OutputIterator
copy (InputIterator first, InputIterator last, OutputIterator result);
Copy range of elements Copies the elements in the range [first,last)
into the range beginning at result.
您正在使用类型为 const char* 的输入迭代器。输出迭代器的类型为 int*.
复制函数从头到尾迭代,导致 4 次迭代。每次迭代在输入中每次前进一个字节。但是输出迭代器是 int* 类型的,所以每次迭代输出迭代器前进 4 个字节。这导致您的 4 个输入字节被复制,每个字节之间有 3 个字节的分隔。
由于要接收该数据的元素是变量 i,它只能保存一个 int(4 字节),这会导致未定义的行为,表现为在未指定的内存位置写入。最有可能将 RET 指令所需的方向覆盖为 return 从相应的 CALL。
在 debian 中不会发生这样的事情取决于那里编译器的内存模型。你不能相信它是一致的。
在仍然使用 std::copy 的同时解决它的一种方法是使用 char* 迭代器作为输出迭代器:
char* ptrDest = reinterpret_cast<char*>(&i);
std::copy(&data[*ind], &data[*ind+sizeof(int)], ptrDest); // i) STD::COPY