UndefinedBehaviorSanitiser 问题 - CS50 Vigenere

Posted

技术标签:

【中文标题】UndefinedBehaviorSanitiser 问题 - CS50 Vigenere【英文标题】:UndefinedBehaviorSanitiser Issue - CS50 Vigenere 【发布时间】:2019-11-01 03:51:55 【问题描述】:

我正在研究 Vigenere (CS50),当我使用任何通过初始筛选的参数运行程序时,我会不断收到“UndefinedBehaviorSanitiser SEGV on Unknown Address”。

我已阅读有关此问题的信息,但找不到解决方案。我尽可能地减少了我的代码,发现即使我做了这部分也会出现问题。问题出在哪里? 非常感谢。

#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

//int shift(char c);

int main(int argc, string argv[])

    if (argc != 2)
        
        printf("Usage: ./vigenere keyword");
        return 1;
        
    else
        
        for (int i = 0; i < strlen(argv[1]); i++)
            
            if (!isalpha(argv[1]))
            
                printf("Usage: ./vigenere keyword");
                return 1;
            
            else
            
                printf("All good!");
                return 1;
            
         
    

【问题讨论】:

argv[1]stringisalpha() 的参数必须是 char。这甚至是如何在没有关于类型不匹配的警告的情况下编译的? isalpha(argv[1]) 应该是isalpha(argv[1][i]) 最准确的应该是isalpha((unsigned char)argv[1][i]),其他一切都是错误的,并可能导致未定义的行为,包括您的崩溃。 @Barmar 不幸的是,GCC 没有给出任何诊断信息。 @Remitto 我赞成您的问题,因为您已经设法生成了一个几乎完美的最小示例来演示问题所有编译器诊断(没有),以及解释发生了什么。为了变得更好,您可以验证崩溃确实发生在 isalpha 行(您可以将整个调用替换为 1 然后 0 并验证它是否正常工作)。 【参考方案1】:

修复确实是

if (!isalpha((unsigned char)argv[1][i]))

isalpha 函数/宏只接受一个整数,它必须具有单个字符的值 unsigned char。但是argv[1]是指向多个字符的指针!

现在作为一个额外的复杂因素,isalpha 通常被实现为一个宏,并且经常被编码以便编译器不会为错误类型的参数生成任何诊断。这很不幸,但您只需要在使用 C 编程时需要了解这些。

charunsigned char 的转换也是必需的 - 如果不需要,那么任何扩展字符(例如 ä)将在 char 签名的平台上调用未定义的行为 - 并且它们 在 x86 处理器上 - 因为该值将是负数,但 isalpha 只期望一个数字,该数字要么是 EOF,要么是一个小于或等于 UCHAR_MAX 的非负数。

【讨论】:

感谢您的详尽解释。我几乎没有发布这个,因为我预计我错过了一些基本的东西,我觉得自己像个白痴,我没有错。感谢您指出这一点,我会再试一次。

以上是关于UndefinedBehaviorSanitiser 问题 - CS50 Vigenere的主要内容,如果未能解决你的问题,请参考以下文章