我如何信任声明const的C ++函数的行为?

时间:2009-02-08 14:28:29

标签: c++ memory-management

这是一个C ++灾难,请查看此代码示例:

#include <iostream>

void func(const int* shouldnotChange)
{
    int* canChange = (int*) shouldnotChange;
    *canChange += 2;
    return;
}


int main() {
    int i = 5;
    func(&i);
    std::cout << i;
    return 0;
}

输出为7!

那么,如果它能够改变一个假设为常数的参数,我们怎样才能确定C ++函数的行为??

编辑:我不是在问我如何确保我的代码按预期工作,而是我想知道如何相信别人的功能(例如某些dll库中的某些功能)不会改变参数或拥有某些行为......

8 个答案:

答案 0 :(得分:21)

根据您的编辑,您的问题是“我怎么能相信第三方代码不是傻瓜?”

简短的回答是“你做不到”。如果您无权访问源代码,或者没有时间对其进行检查,那么您只能信任作者拥有书面的合理代码。在您的示例中,函数声明的作者明确声明代码不会使用const关键字更改指针的内容。您可以信任该声明,也可以不信任。正如其他人所建议的那样,有一些测试方法,但如果你需要测试大量的代码,那将是非常耗费人力的。也许比阅读代码还要多。

如果你是在一个团队工作,并且你有一个团队成员写这样的东西,那么你可以和他们谈谈它并解释它为什么不好。

答案 1 :(得分:12)

通过编写理智的代码。 如果您编写的代码是您无法信任的,那么显然您的代码将不值得信任。 几乎任何语言都可以使用类似的愚蠢技巧。在C#中,您可以通过反射在运行时修改代码。您可以检查和更改私有类成员。你如何防范这种情况?你没有,你只需要编写符合你期望的代码。

除此之外,编写一个单元测试,测试该函数不会改变其参数。

答案 2 :(得分:9)

C ++中的一般规则是该语言旨在保护您免受Murphy的攻击,而不是Machiavelli。换句话说,它意味着让维护程序员不会意外地更改标记为const的变量,而不是让某人不能更改它,这可以通过多种方式完成。

答案 3 :(得分:7)

C式演员表示所有投注均已关闭。这有点像告诉编译器“相信我,我知道这看起来很糟糕,但我需要这样做,所以不要告诉我我错了。”而且,你所做的实际上是未定义的。抛弃常量,然后修改值意味着编译器/运行时可以做任何事情,包括例如你的程序崩溃。

答案 4 :(得分:2)

不要在C ++中使用C样式转换 我们在C ++中有4个强制转换操作符(此处按危险顺序列出)

  • 的static_cast&LT;&GT;安全(用于'转换数字数据类型')。
  • 的dynamic_cast&LT;&GT;安全(但抛出异常/返回NULL)
  • 的const_cast&LT;&GT;危险(删除const时)。
  • 的static_cast&LT;&GT;非常危险(用于投射指针类型。不是一个好主意!!!!!)
  • 的reinterpret_cast&LT;&GT;非常危险。只有在您了解后果的情况下才能使用此功能。

你总是可以告诉编译器你知道的比它更好,并且编译器会接受你的面值(原因是你不希望编译器在你真正知道更好的时候妨碍你)。 / p>

强大的编译器是一把双刃剑。如果你知道自己在做什么,这将是一个有用的强大工具,但如果你弄错了,它会在你的脸上爆炸。

不幸的是,编译器有大多数事情的原因,所以如果你超越它的默认行为,那么你最好知道你在做什么。演员是一件事。很多时候它很好。但是如果你开始抛弃const(ness),那么你最好知道你在做什么。

答案 5 :(得分:2)

我唯一可以建议的是从标记为只读的内存页面中分配变量shouldNotChange。如果应用程序尝试写入该内存,这将强制OS / CPU引发错误。我并不是真的推荐这个作为验证函数的一般方法,就像你可能觉得有用的想法一样。

答案 6 :(得分:2)

执行此操作的最简单方法是不传递指针:

void func(int shouldnotChange);

现在将复制该参数。该函数可以随意更改所有值,但不会修改原始值。

如果您无法更改函数的界面,那么您可以在调用函数之前复制该值:

int i = 5;
int copy = i
func(&copy);

答案 7 :(得分:0)

(int*)是来自C的转换语法.C ++完全支持它,但不推荐使用它。

在C ++中,等效演员应该是这样编写的:

int* canChange = static_cast<int*>(shouldnotChange);

事实上,如果你写的那样,编译器就不会允许这样的演员表。

你正在做的是编写C代码并期望C ++编译器能够捕捉到你的错误,如果你考虑它会有点不公平。