gpt4 book ai didi

c++ - 为什么C++(Visual Studio)数据类型没有停止在其极限上?

转载 作者:行者123 更新时间:2023-12-01 14:54:02 24 4
gpt4 key购买 nike

通常,如果数据类型停止工作(程序崩溃或其他任何原因),而不是如果超出其限制则没有任何信息,那将更安全,更好(例如避免使用UB)。

例如,unsigned char的限制为 255 ,现在让我们说值3000作为unsigned char存储在文本文件中,并加载到C++程序中。它不会给出任何错误或其他信息,而是unsigned char会执行一些自动转换(或UB?)并提供另一个低于其限制的值。但为什么?那有什么用?

如果超出了用于处理值的数据类型,有什么方法可以使用Visual Studio构建的程序停止工作(崩溃或发出警报等)?

与带符号/无符号数据类型相同,如果您使用无符号,但是以某种方式加载“-1”值,则无符号数据类型只是“接受”它,但会为您提供大于0的其他值。

最佳答案

在大多数情况下,缺少检查的最重要原因是性能。 C++遵循不买不买的原则。如果需要检查,请编写一个自定义类型进行检查。您甚至可以让它仅在 Debug模式下进行检查。 (例如std::vector会在其operator[]中执行此操作。)如果您想使用安全的语言,C++是您的最差选择(紧随C和汇编之后)。 ;-)但是您可以选择其他许多高级语言。

为了进行调试检查,标准库中有一个宏: assert() :

#ifdef NDEBUG
#define assert(condition) ((void)0)
#else
#define assert(condition) /*implementation defined*/
#endif

由此, /*implementation defined*/部分检查 condition。如果结果为 false,则通常会调用 abort() ,这又会立即中止该过程(通常会产生可在调试器中评估的核心转储)。

Is there any way, to make programs build with Visual Studio stop working (crashing or give an alert etc.) if the data type which is used to handle the value is exceeded?

Same with signed/unsigned data types, if you use unsigned, but you load "-1" value somehow, the unsigned data type is just "accepting" it but gives you some other value above 0.



是的,有一种方法–使用自定义类型作为原始文档的包装。

一个简单的示例来证明这一点:

#include <cassert>
#include <iostream>

struct UChar {
unsigned char value;

UChar(unsigned char value = 0): value(value) { }
UChar(char value): value((assert(value >= 0), (unsigned char)value)) { }
UChar(int value): value((assert(value >= 0 && value < 256), value)) { }
UChar(unsigned value): value((assert(value < 256), value)) { }
UChar(long value): value((assert(value >= 0 && value < 256), value)) { }
UChar(unsigned long value): value((assert(value < 256), value)) { }
UChar(long long value): value((assert(value >= 0 && value < 256), value)) { }
UChar(unsigned long long value): value((assert(value < 256), value)) { }
UChar(const UChar&) = default;
UChar& operator=(const UChar&) = default;
~UChar() = default;

operator unsigned char() { return value; }
};

#define PRINT_AND_DO(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__

int main()
{
// OK
PRINT_AND_DO(UChar c);
PRINT_AND_DO(std::cout << "c: " << (unsigned)c << '\n');
PRINT_AND_DO(c = 'A');
PRINT_AND_DO(std::cout << "c: " << c << '\n');
PRINT_AND_DO(UChar d = 'B');
PRINT_AND_DO(std::cout << "d: " << d << '\n');
PRINT_AND_DO(d = c);
PRINT_AND_DO(std::cout << "d: " << d << '\n');
// This will crash if NDEBUG not defined:
//PRINT_AND_DO(UChar e(3000));
//PRINT_AND_DO(c = 3000);
PRINT_AND_DO(d = -1);
}

输出:

a.out: main.cpp:9: UChar::UChar(int): Assertion `value >= 0 && value < 256' failed.
UChar c;
std::cout << "c: " << (unsigned)c << '\n';
c: 0
c = 'A';
std::cout << "c: " << c << '\n';
c: A
UChar d = 'B';
std::cout << "d: " << d << '\n';
d: B
d = c;
std::cout << "d: " << d << '\n';
d: A
d = -1;
bash: line 7: 31094 Aborted (core dumped) ./a.out

Live Demo on coliru

注意:

这仅是一个演示,不是生产就绪代码。例如。由于转换运算符 operator unsigned char()会导致包装实例在 unsigned char中没有重载(但支持 struct UChar)时使用,因此包装器实例将转换回 unsigned char,因此未捕获到加法或减法中的下溢。要解决此问题,必须为 UChar重载更多运算符。但是,我相信演示足以说明该原理。

关于c++ - 为什么C++(Visual Studio)数据类型没有停止在其极限上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59298550/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com