【问题标题】:Warnings causing bug in the .exe?导致 .exe 中的错误的警告?
【发布时间】:2012-11-27 02:01:48
【问题描述】:

嘿,我只是想知道这些警告是否会导致 .exe 在启动时崩溃。 以下是警告:

Warning 1   warning C4244: '=' : conversion from 'double' to 'int', possible loss of data   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\stats.cpp 54  1   MaroonedCA2
Warning 2   warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\player.cpp    75  1   MaroonedCA2
Warning 3   warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\player.cpp    92  1   MaroonedCA2
Warning 4   warning C4018: '<' : signed/unsigned mismatch   c:\users\conor\documents\college\dkit - year 2 - repeat\dkit - year 2 - semester 1 - repeat\games programming\maroonedca2\maroonedca2\inventory.cpp 63  1   MaroonedCA2

1

int stats[SIZE];
    stats[0] = Status.health;
    stats[1] = Status.strength;
    stats[2] = Status.hitpoints;
    stats[3] = Status.armour;
    stats[4] = Status.luck;

运气是双重的,没有被施放。

2

 int Player :: hitPoints()
    {
        srand(time(0)); // seed random number generator based on current time
        int randomNumber= rand(); // generate random number
        int hitPoints = (randomNumber% 15) + 1; // get a number between 1 and 20
        return hitPoints;
    }

3

int Player :: fatigue()
{
    srand(time(0)); // seed random number generator based on current time
    int randomNumber= rand(); // generate random number
    int fatigue = (randomNumber% 5) + 1; // get a number between 1 and 5
    return fatigue;
}

4

for (int i= 0; i< inventory.size(); ++i)
        cout<< inventory[i] << endl;
    }
    cout << "\n-----------------------------------------\n";

【问题讨论】:

  • 我看不到。但是您应该了解这些警告的含义,它们很容易修复,最好不要养成编写生成它们的代码的习惯。
  • 好吧,警告对生成的代码没有影响,所以没有。但是,警告可能表明您的代码中存在可能导致崩溃的错误。 (或者您可能有这样的错误并且没有警告。)上述警告比直接导致崩溃的警告更暗示数据丢失,但可能存在导致崩溃的循环控制或数组索引问题。 (最好检查每个警告,了解发出警告的原因,如果它是“非问题”,则插入显式强制转换或其他任何内容以使其静音并表明您了解问题。)

标签: c++ warnings


【解决方案1】:

我认为唯一有可能导致崩溃的将是最后一个。如果inventory.size() &gt; INT_MAX,那么在一个典型的实现中,你最终会从一个负索引中读取。

假设您的程序实际上在启动过程中崩溃了,但如果这是问题的根源,我会感到相当惊讶。这更像是一种理论上的可能性,而不是可能的问题来源。首先,在启动时,我猜inventory.size() 可能是0,所以不会发生溢出。其次,我猜你只显示库存以响应命令,而不是在启动期间 - 所以这段代码可能不会在启动期间执行。

其他有问题,但根本没有可能导致崩溃的问题。

例如,您的示例 #2 和 #3 错误地使用了 srand —— 大多数正常程序,几乎可以肯定包括这个程序,应该准确地调用 srand 一次,因为程序是启动,并且永远不会再调用它。这将导致您的“随机”数字比应有的更可预测,但不会导致崩溃。

【讨论】:

    【解决方案2】:

    单独来看,这些警告都不会导致崩溃。但是,它们可能会导致其他函数被错误地调用,从而无法很好地响应意外值。

    您应该获得崩溃的堆栈跟踪,以了解它发生的原因。调试是一个单独的主题,您可以通过 Google 获得大量信息:)

    【讨论】:

      【解决方案3】:

      你的程序会崩溃吗?

      通常这些警告不会引起太多问题,除非您错过了程序中的一些特殊情况,例如将 double 转换为 int 但不检查此 int 是否变为 0 并且除以 0。

      让我们来看看所有的警告:

      Warning 1   warning C4244: '=' : conversion from 'double' to 'int', possible loss of data
      

      很明显 int 不能存储 double 的所有值,但是转换它并没有错,只要您记住它可能已成为可能导致问题的值(例如转换为 0),但是这取决于你用你的 int 做什么。试试int toint = static_cast&lt;int&gt;(yourdouble); 应该不会发出警告。

      Warning 2   warning C4244: 'argument' : conversion from 'time_t' to 'unsigned int', possible loss of data
      

      time_t 通常有 8 个字节,uint 只有 4 个,所以显然它不能在里面存储所有信息。当您期望一个值但得到一个不同的值时,数据丢失可能会导致混淆。

      Warning 4   warning C4018: '<' : signed/unsigned mismatch
      

      同样没有问题。它只是告诉您,一方面可能是负值,另一方面是不可能的,或者一侧的最大值高于另一侧的最大值。非常常见的警告,通常是由于程序员在只需要无符号时懒惰地将整数定义为无符号而发生的。

      编辑: 我假设你正在使用 VC。这是一个关于如何忽略警告的示例,如果您确定无法摆脱它们并且它们是完全可以忽略的(我强烈建议使用 once 参数):

      http://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

      【讨论】:

        【解决方案4】:

        每个警告都表明有些地方不太正确。这可能会影响其他代码。


        在……

        int stats[SIZE];
        stats[0] = Status.health;
        stats[1] = Status.strength;
        stats[2] = Status.hitpoints;
        stats[3] = Status.armour;
        stats[4] = Status.luck;
        

        使用double 类型的Status.luck,您要么丢失信息,要么使用了过于通用的类型。信息丢失可能会导致以后崩溃。过于笼统的类型可能会导致其他地方出现错误。

        解决方法取决于这两种可能性中的哪一种。


        在

        int Player :: hitPoints()
        {
            srand(time(0)); // seed random number generator based on current time
            int randomNumber= rand(); // generate random number
            int hitPoints = (randomNumber% 15) + 1; // get a number between 1 and 20
            return hitPoints;
        }
        

        您依赖于从 time(0) 类型到 srand 参数类型的隐式转换。

        time 可能可以作为游戏的熵源(但不适用于重复调用的掷骰子程序)。但请在此处使用static_cast。到记录的正式参数类型。


        在

        int Player :: fatigue()
        {
            srand(time(0)); // seed random number generator based on current time
            int randomNumber= rand(); // generate random number
            int fatigue = (randomNumber% 5) + 1; // get a number between 1 and 5
            return fatigue;
        }
        

        您正在重新初始化随机数生成器。这很可能是一个错误。我无法想象您希望每次玩家感到疲劳时都重复相同的行为。


        在

        for (int i= 0; i< inventory.size(); ++i)
            cout<< inventory[i] << endl;
            }
        cout << "\n-----------------------------------------\n";
        

        您缺少一些大括号或大括号,和/或缩进问题。不幸的是它编译了。但是修复它。

        有符号/无符号不匹配是关于有符号i 与来自inventory.size() 的无符号size_t 的比较。在某些情况下,这可能会导致令人讨厌的错误。例如,表达式

        string( "hello" ).size() < -3
        

        将始终为 true,因为 隐式提升 -3 为无符号类型,带有环绕。这是非常愚蠢的。非常值得关注。

        循环的最佳解决方法是使用 size 函数将大小值转换为有符号,例如

        typedef ptrdiff_t Size;
        
        template< class Item >
        Size size( std::vector<Item> const& v ) { return v.size(); }
        

        然后

        for (int i= 0; i < size( inventory ); ++i)
        {
            cout<< inventory[i] << endl;
        }
        

        这集中了解决方案,使其适用于所有未来的代码。

        将循环控制变量更改为无符号类型只会将问题(尤其是隐式转换问题)推到另一个地方。请注意,通常您不会收到任何关于此类隐式转换的警告。大多数编译器只对直接比较发出警告。

        对于更通用的size 函数,您可以将其定义为

        template< class Container >
        Size size( Container const& c ) { return end( c ) - begin( c ); }
        

        其中begin 和end 是来自&lt;utility&gt; 标头的C++11 函数。

        【讨论】:

          猜你喜欢
          • 2019-01-28
          • 2013-08-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-11
          • 1970-01-01
          • 2017-11-03
          • 1970-01-01
          相关资源
          最近更新 更多