我正在尝试修复非常老的C代码中的一个错误,该错误最近在我们将Visual Studio更新到2017版之后在Windows上突然弹出。该代码仍在多个Linux平台上运行。这告诉我,我们可能依赖于一些未定义的行为,我们以前很幸运。
我们有很多这样的函数调用:
get_some_data(parent,“ ge”,“”,type);
在调试中运行时,我注意到在进入此函数后,在函数执行任何操作之前,空字符串立即被垃圾填充。该函数的声明如下:
static void get_some_data(
KEY Parent,
char *Prefix,
char *Suffix,
ENT EntType)
那么直接传递字符串(“ ge”,“”)是否不明智?我知道通过声明char * suffix =“”并传递后缀而不是“”来解决此问题很简单,但是我现在在质疑是否需要遍历整个代码集来寻找这种类型的函数调用。
那么直接传递字符串(“ ge”,“”)是否不明智?
通常,将字符串文字传递给函数没有内在的错误。
但是,将指针(传入)特别是声明为指向非const
char指针的参数的字符串文字传递是不明智的,因为C指定尝试修改字符串文字会导致未定义的行为,并且在实践中,UB通常表现为突然的程序终止。如果一个函数声明一个参数为,const char *
那么您可以合理地认为它不会尝试修改该指针的目标-这是您需要确保的-但如果它声明一个参数为,char *
则不会这样答应了,函数甚至没有办法在运行时检查参数是否可写。
可能您可以依靠文档来代替const
-qualification,因为在这方面您还可以,只要在实践中不尝试修改字符串文字即可,但是与其他方式相比,您仍然更容易遇到错误。
我知道通过声明char * suffix =“”并传递后缀而不是“”来解决此问题很简单
此类更改可能掩盖了您在编译器中所做的工作,因此它不会警告函数调用,但不会解决任何问题。相同的指针值以任何一种方式传递给函数,并且应用相同的语义和约束。同样,如果编译器对函数调用发出警告,则它也应对分配发出警告。
顺便说一下,这在C ++中不是问题,或者至少不是同一问题,因为在C ++中,字符串文字首先表示的是数组const char
。
,但是我现在在质疑是否需要遍历整个代码集来寻找这种类型的函数调用。
最好修改被调用函数的签名。如果希望传递字符串文字,可以确保该参数具有type const char *
,如下所示:
static void get_some_data(
KEY Parent,
const char *Prefix,
const char *Suffix,
ENT EntType)
但是请注意,这很可能会引起有关const正确性违反的新警告。为了确保安全,您也需要修理这些东西,而不会丢掉const
东西。可以很好地进行级联,但是该练习肯定会帮助您确定和修复代码对字符串文字处理不当的位置。
另一方面,可能不太普及的真正解决方法是将指针传递给可修改的数组,而不是(不可修改的)字符串文字。也许正是您所建议的修复程序所考虑的,但这的正确方法是:
char prefix[] = "ge";
char suffix[] = "";
get_some_data(parent, prefix, suffix, type);
在这里,prefix
和suffix
是单独的(可修改的)本地数组,使用字符串文字内容的副本进行初始化。
综上所述,我倾向于怀疑,如果您在使用VS编译的可执行文件而不是与GCC编译的可执行文件之间遇到与这些参数相关的真正的运行时错误,则可能是其他原因。我的第一个猜测是数组界限被超出。我的第二个猜测是,您正在将C代码编译为C ++,并且碰到它们之间的一个或多个(其他)差异。
这并不是说您不应该const
对这里涉及的本质/可写性问题有个很好的了解,但是整个练习只是为了确定您可以开始,这很糟糕。您仍然可以得到更好的代码,但是当老板询问为什么还没有修复该错误时,要把它卖给老板会有些棘手。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句