我有这个代码来复制一个整数:
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 。
然后,我编译并运行嵌入式Arm 上的代码(sizeof(int)
也是4)。带有 i)的代码似乎也在运行,在函数中打印预期。
但是,从函数返回时会导致问题。
我也尝试了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嵌入式上工作?
答案 0 :(得分:8)
std::copy(&data[*ind], &data[*ind+sizeof(int)], &i);
这会将sizeof(int)
个字节复制到从int
开始的&i
数组的连续元素,不用说这会导致未定义的行为,因为&i
处没有数组。< / p>
你可能意味着
std::copy(&data[*ind], &data[*ind+sizeof(int)], reinterpret_cast<char*>(&i));
memcpy
工作的原因是因为它显式地复制了字节,std::copy
更通用,就像它在抽象迭代器上运行的其他标准算法一样,由您决定是否正确调用它。
答案 1 :(得分:1)
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指令返回到相应CALL所需的方向
在debian中不会发生这样的事情取决于编译器的内存模型。你不能相信它是一致的。
在使用std :: copy时解决它的一种方法是使用char * iterator作为输出迭代器:
char* ptrDest = reinterpret_cast<char*>(&i);
std::copy(&data[*ind], &data[*ind+sizeof(int)], ptrDest); // i) STD::COPY
答案 2 :(得分:-2)
您的ARM CPU可能不支持未对齐的内存访问。 memcpy
会为你处理这种情况。