我正在使用-Werror
进行编译,并发现警告已转换为错误:
1> cc1plus.exe: warnings being treated as errors
1> c:\rtems-4.9\bin\../lib/gcc/powerpc-rtems4.9/4.3.2/include/c++/bits/stl_vector.h: In function 'int someFunc()':
1> D:\Git\Error_Parsing_script\Src\Plus\RTEMS_proj\c:\rtems-4.9\bin\..\lib\gcc\powerpc-rtems4.9\4.3.2\include\c++\bits\stl_vector.h(1043,1) : error: array subscript is above array bounds
从这段代码:
struct ControllerConfigDataType1 {
char name[50];
int controllerType;
};
int someFunc()
{
std::vector<char> reply;
reply.reserve(255);
ControllerConfigDataType1 response = { { 0 } };
reply.insert(reply.end(), reinterpret_cast<char*>(&response), reinterpret_cast<char*>(&response) + sizeof(response));
return 0;
}
据我所知,this code is completely valid。一个特殊的事情是,如果我手动将sizeof(resonse)
设置为&lt; = 50(char数组的大小),那么我们不会得到任何错误。似乎这个错误来自于尝试超出char name[50]
中response
数组的范围,我认为我的指针取消引用reinterpret_cast<char*>(&response) + sizeof(response)
是有意义的。
知道ControllerConfigDataType1
的格式无法更改,有没有办法满足编译器对此行的预留?
请注意,这是来自RTEMS 4.9.2的稍微旧的编译器(请参阅下面的详细信息),这可能意味着此警告不会出现在更新版本的GCC中(并且不会出现在Visual C ++中VS2015)。
错误提到了stl_vector.h(1043,1)
函数的实现std::vector::insert
:
// Called by the range insert to implement [23.1.1]/9
template<typename _InputIterator>
void
_M_insert_dispatch(iterator __pos, _InputIterator __first,
_InputIterator __last, __false_type)
{
typedef typename std::iterator_traits<_InputIterator>::
iterator_category _IterCategory;
_M_range_insert(__pos, __first, __last, _IterCategory());
}
从库中检索到的缩进
请注意,编译器由RTEMS 4.9.2
提供,并具有以下版本信息:
Thread model: rtems
gcc version 4.3.2 (GCC)
答案 0 :(得分:2)
获取对象字节的一种好方法是使用memcpy
,并让字节类型为unsigned char
。它很好,因为神圣标准至少有一个这样的例子,所以如果一个编译器扼杀了它,那么很容易说,嘿,这个编译器在标准的例子上扼杀,让&# 39;停止使用它。即使ISO标准中的例子是非规范性的。
您的原始示例,使用此方法:
int someFunc1()
{
std::vector<unsigned char> reply;
reply.reserve(255); // Note: this, from original example, is only an optimization.
ControllerConfigDataType1 response = { { 0 } };
// reply.insert(reply.end(), reinterpret_cast<char*>(&response), reinterpret_cast<char*>(&response) + sizeof(response));
int rs = reply.size(); int ds = sizeof(response); reply.resize(rs+ds); memcpy(&reply[rs], &response, ds);
return 0;
}
此代码假定int
足以满足此处使用的vector
的大小,这对于网络数据包是合理的:它不能很好地为2 GB或更多。否则,将int
替换为ptrdiff_t
。可能重命名为Size
。
更一般地说,你可以抽象并集中它,这有助于测试和维护,如下所示:
#include <stddef.h> // ptrdiff_t
#include <string.h> // memcpy
#include <type_traits> // std::is_trivially_copyable
#include <utility> // std::enable_if_t
using Byte = unsigned char;
using Size = ptrdiff_t;
template< class Type
// The following sanity-check line must be removed for a C++03 compiler:
, class Enabled_ = std::enable_if_t< std::is_trivially_copyable< Type >::value >
>
void append_to( std::vector<Byte>& v, Type const& o )
{
Size const n_v_bytes = v.size();
Size const n_o_bytes = sizeof( o );
v.resize( n_v_bytes + n_o_bytes );
memcpy( &v[n_v_bytes], &o, n_o_bytes );
}