C ++编译器愉快地编译了此代码,没有警告:
int ival = 8;
const char *strval = "x";
const char *badresult = ival + strval;
在这里,我们将char *指针值(strval)添加到int值(ival)并将结果存储在char *指针(badresult)中。当然,badresult的内容将是全部垃圾,当应用程序尝试在其他地方使用badresult时,该应用程序可能会在此行或稍后崩溃。问题是在现实生活中容易犯这样的错误。我在我的代码中发现的代码如下所示:
message += port + "\n";
(其中message是使用其运算符+ =函数处理结果的字符串类型; port是int且\ n显然是const char指针)。
有什么方法可以禁用这种行为并在编译时触发错误?
我看不到将char *添加到int的任何正常用例,并且我想找到一种解决方案,以防止在我的大型代码库中出现这种错误。使用类时,我们可以创建私有运算符并使用explicit关键字禁用不需要的转换/广播,但是现在我们正在谈论基本类型(char *和int)。
一种解决方案是使用clang,因为clang具有用于启用警告的标志。但是我不能使用clang,所以我正在寻找一种触发编译器错误的解决方案(某种操作员重载或使用某些定义进行修饰以防止此类构造或任何其他想法)。
有什么方法可以禁用这种行为并在编译时触发错误?
一般而言,因为您的代码与以下合法代码非常相似:
int ival = 3;
const char *strval = "abcd";
const char *goodresult = ival + strval;
这里goodresult
所指向的最后一个字母d
的strval
。
顺便说一句,在Linux上,已知getpid(2)返回一个正整数。因此,您可以想象:
int ival = (getpid()>=0)?3:1000;
const char *strval = "abcd";
const char *goodresult = ival + strval;
从道德上讲,它与前面的示例相同(因此我们人类知道,ival
始终为3)。但教学,编译器getpid()
不返回负值在实践中是棘手的(返回类型pid_t
的getpid
一些签名整数,并已被签名是由可用叉(2) ,这可能给-1)。您可以想象更多奇怪的例子!
您需要编译时检测缓冲区溢出(或更一般而言,未定义的行为),并且通常与停止问题等效(这是无法解决的问题)。因此,一般来说这是不可能的。
当然,可以声称聪明的编译器可以针对您的特定情况发出警告,但随后担心哪些情况应该对警告有用。
您可以尝试使用某些静态源程序分析工具,例如Clang静态分析器或Frama-C(具有其最新的Frama-C ++变体),或者某些昂贵的专有工具,例如Coverity等。这些工具不能静态地检测所有错误,并且比优化编译器花费更多的时间来执行。
您可以(例如)编写自己的GCC插件来检测此类错误(这意味着要开发自己的静态源代码分析器)。您将花费数月的时间编写它。您确定值得付出努力吗?
但是我不能用c
为什么?您可以在开发过程中(而非用于生产)请求使用clang静态分析器(或其他方法)的许可。如果您的经理拒绝,则将成为管理问题,而不是技术问题。
我看不到将char *添加到int的任何正常用例
您需要更多的想象力。想像
puts("non-empty" + (isempty(x)?4:0));
好的,这不是很易读的代码,但这是合法的。在上个世纪,当内存成本很高时,一些人曾经使用这种方式进行编码。
今天您可能会编码
if (isempty(x))
puts("empty");
else
puts("non-empty")
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句