【问题标题】:UndefinedBehaviorSanitizer becouse of nullpointerUndefinedBehaviorSanitizer 因为空指针
【发布时间】:2019-11-06 15:42:32
【问题描述】:

Hej,我有一些 C 代码,可以正常工作。我只是想从 typedef 土豆到我的结帐功能得到一个价格。我“//”未使用的代码。我需要更多信息,请尽管问,但我不知道如何解决这个问题。非常感谢任何帮助。

 #include <stdio.h>
 #include <string.h>   

    int number;

    void get_number ( );
    void show_menu ( );
    int get_input ( );
    void chech_out ();

    struct Product 
    {
            float potatoes;
    };
    typedef struct Product product;

    int main (void)
    {
        struct Product product;

        while (1)
        {
            //show_product1 ();
            show_menu ();
            if (get_input ()) // end on "a"
                break;
        }
        printf ("Bye!");
        return 0;
    }



    void show_menu (void)
    {
        printf ("Type what you wanne do");
        printf ("f)change amount    h)chech out    s)Strawberry");
        printf ("c)carrots    p)potatoes  o)Onion");
        printf ("a)quit");
    }

    void get_number ( )
    {

        printf ("Enter number in kg: ");
        scanf ("%d", &number);
    }



    int get_input (struct Product *product )
    {
        char letter;

        scanf ("%c", &letter);
        switch (letter)
        {
            case 'f':
                printf("\n\n\nWhenever you enter a new amount it will reset the old one!\n\n");

                break;
            case 'h':
                chech_out();


                break;
            case 'c':

                break;
            case 'p':


                get_number();           
                float P_freightPrice = number*12;
                float P_kgPrice = number*25;
                float P_totalprice=P_freightPrice+P_kgPrice;
                product->potatoes = P_totalprice;
           printf("\n%f\n",P_totalprice);     

         if (P_totalprice <= 100)
         {
           printf("%f\n",P_totalprice);    
         }
         if (P_totalprice>=101 && number<=350)
         {
             float New=(P_totalprice/100)*5;
             float total=P_totalprice-New;
             printf("%f\n",total);    
         }
         if(P_totalprice>=351 && P_totalprice<=600)
         {
             float New=(P_totalprice/100)*10;
             float total=P_totalprice-New;
             printf("%f\n",total); 

         }
        if(P_totalprice>=601)
        {
             float New=(P_totalprice/100)*15;
             float total=P_totalprice-New;
             printf("%f\n",total);    
        }  

                break;
            case 'a':
                return 1;
            default:
                ;
        }
        return 0;
    }

    void chech_out (struct Product *product)
    {
        printf("%2.f",product->potatoes);
    }

我收到错误消息:

hj4.c:181:28: runtime error: member access within null pointer of type 'struct Product'
hj4.c:181:28: runtime error: load of null pointer of type 'float'
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==1476==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000422814 bp 0x7ffd19c2f280 sp 0x7ffd19c2f260 T1476)
==1476==The signal is caused by a READ memory access.
==1476==Hint: address points to the zero page.
    #0 0x422813  (/root/sandbox/hj4+0x422813)
    #1 0x42246e  (/root/sandbox/hj4+0x42246e)
    #2 0x42232a  (/root/sandbox/hj4+0x42232a)
    #3 0x7f11cd86fb96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x402ae9  (/root/sandbox/hj4+0x402ae9)

UndefinedBehaviorSanitizer can not provide additional info.
==1476==ABORTING

我想我只需要一些指针来解决这个问题;)

【问题讨论】:

  • 使用floatdouble 等不精确的数据类型不适合保存货币值,它们在计算时可能会给你“奇怪”的结果。通常也不建议使用全局变量来传递函数参数或返回值。它使函数非线程安全、不可重入、浪费内存,最重要的是,难以阅读,尤其是当您使用非描述性名称时,例如 number
  • 您在编译程序时是否收到任何编译警告?如果没有,请使用-Wall 打开警告。然后尝试理解并修复警告。如果您对此有任何疑问,我建议您发布一个包含警告消息的新问题。

标签: c typedef null-pointer


【解决方案1】:

我不知道为什么您的编译器没有对此发出警告,但您的 chech_out 函数在顶部声明为 chech_out() - 没有参数 - 但 定义 包括一个:@ 987654323@。当函数被调用时,它将堆栈上的垃圾视为指向产品的指针,并且失败了。

编辑:编译器没有发出警告的原因是因为仅使用开闭括号声明函数意味着参数列表未定义(与旧版本的 C 兼容):如果函数确实不带参数,则定义它们为int myfunction(void),其中void 表示“我不带参数”

解决这个问题

// define struct Product here
void get_number (void);
void show_menu (void);
int get_input (struct Product *);
void chech_out (struct Product *);

现在让你的编译器告诉你你错过了什么。

【讨论】:

    【解决方案2】:

    谢谢大家,我尝试了史蒂夫的代码,现在我遇到了一个我不明白的编译问题。 代码的唯一变化是:

    void get_number (void);
    void show_menu (void);
    int get_input (struct Product *);
    void chech_out (struct Product *);
    int number;
    

    我得到错误:

    hj4.c:35:18: error: too few arguments to function call, expected 1, have 0
                    if (get_input ()) // end on "a"
                        ~~~~~~~~~  ^
    hj4.c:21:1: note: 'get_input' declared here
    int get_input (struct Product *);
    ^
    hj4.c:73:14: error: too few arguments to function call, expected 1, have 0
                            chech_out();
                            ~~~~~~~~~ ^
    hj4.c:22:1: note: 'chech_out' declared here
    void chech_out (struct Product *);
    ^
    2 errors generated.
    

    我确实尝试将代码更改为

    void get_number (void);
    void show_menu (void);
    int get_input (struct Product *product);
    void chech_out (struct Product *product);
    int number;
    

    但同样的问题来了。

    【讨论】:

    • 编译器告诉你问题出在哪里。 定义(你提供代码主体的地方)说它需要一个指向Product的指针,但是当你调用函数时,你没有传递参数。
    • 很抱歉是金发女郎,但我该怎么做呢?我确实尝试将传递参数放在这样的函数中; if (get_input (struct Product)),但没用
    • 我妻子是金发碧眼的,所以我很同情 :-) 看看你的 get_input 函数,它会提示用户输入一个字符并执行许多其他操作。这个函数需要struct Product *product 作为参数,调用者说“在这里传递你的数据”。 期望得到一个指针。但是,当您在代码前面调用函数时,您并没有传递一个指针:您希望get_input 将您的数据传递到哪里?我的猜测是你想使用main() 内部的product var 调用,所以它会是get_input(&amp;product)
    猜你喜欢
    • 2012-10-24
    • 1970-01-01
    • 2013-01-09
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2011-02-03
    相关资源
    最近更新 更多