如何修复 g++ 内存范围重叠?

Posted

技术标签:

【中文标题】如何修复 g++ 内存范围重叠?【英文标题】:How do I fix a g++ memory range overlap? 【发布时间】:2014-11-22 07:48:56 【问题描述】:

我开发了一个在 Visual Studio 中完美运行的 C++ 程序,它接受一个整数数组、两个 C 字符串数组和一个大 C 字符串,并尝试查找大 C 字符串是否包含其中的任何其他 C 字符串有一定的距离。

编辑:由于这是一项学校作业,我被限制使用 C 字符串而不是 std::string 和 strcopy 而不是 memmove。

当我在 g++ 上运行程序时,我收到以下错误消息:

==17764==ERROR: AddressSanitizer: strcpy-param-overlap: memory ranges [0x7fff7213d993,0x7fff7213d994) and [0x7fff7213d993, 0x7fff7213d994) overlap
    #0 0x7fa2141eec11 in __interceptor_strcpy ../../../../gcc-4.9.2/libsanitizer/asan/asan_interceptors.cc:486
    #1 0x402b2a in standardizeRules(int*, char (*) [21], char (*) [21], int) (/w/home.02/cs/ugrad/justinn/match+0x402b2a)
    #2 0x40176d in main (/w/home.02/cs/ugrad/justinn/match+0x40176d)
    #3 0x376f01ed1c in __libc_start_main (/lib64/libc.so.6+0x376f01ed1c)
    #4 0x4011f8 (/w/home.02/cs/ugrad/justinn/match+0x4011f8)

Address 0x7fff7213d993 is located in stack of thread T0 at offset 787 in frame
    #0 0x401347 in main (/w/home.02/cs/ugrad/justinn/match+0x401347)

  This frame has 7 object(s):
    [32, 48) 'test1dist'
    [96, 144) 'distance'
    [192, 276) 'test1w1'
    [320, 404) 'test1w2'
    [448, 577) 'doc'
    [640, 892) 'word1' <== Memory access at offset 787 is inside this variable
    [928, 1180) 'word2'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
Address 0x7fff7213d993 is located in stack of thread T0 at offset 787 in frame
    #0 0x401347 in main (/w/home.02/cs/ugrad/justinn/match+0x401347)

  This frame has 7 object(s):
    [32, 48) 'test1dist'
    [96, 144) 'distance'
    [192, 276) 'test1w1'
    [320, 404) 'test1w2'
    [448, 577) 'doc'
    [640, 892) 'word1' <== Memory access at offset 787 is inside this variable
    [928, 1180) 'word2'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: strcpy-param-overlap ../../../../gcc-4.9.2/libsanitizer/asan/asan_interceptors.cc:486 __interceptor_strcpy
==17764==ABORTING

是什么导致了这个错误,我该如何解决?

谢谢!

编辑: 代码如下:

int standardizeRules(int distance[], char word1[][MAX_WORD_LENGTH + 1], char word2[][MAX_WORD_LENGTH + 1], int nRules)

    int validCheck = nRules; //validCheck holds the number of actual valid rules to avoid checking known bad rules
    for (int a = 0; a < validCheck; a++) //converts every letter in every string to lowercase
    
        for (int b = 0; b < MAX_WORD_LENGTH; b++)
        
            word1[a][b] = tolower(word1[a][b]);
            word2[a][b] = tolower(word2[a][b]);
        
    
    for (int count = 0; count < validCheck; count++) //repeat rule testing, if a repeat is found it sets distance to 0 so code automatically filters it out
    
        for (int x = count + 1; x < validCheck; x++) //compares current string to all other strings behind it in both arrays
        
            bool repeat = false;
            //cerr << "Testing: " << x << endl;
            if (strcmp(word1[count], word1[x]) == 0)
            
                if (strcmp(word2[count], word2[x]) == 0)
                
                    //cerr << "Repeat rule" << endl;
                    repeat = true;
                
            
            else if (strcmp(word1[count], word2[x]) == 0)
            
                if (strcmp(word2[count], word1[x]) == 0)
                
                    //cerr << "Repeat rule" << endl;
                    repeat = true;
                
            
            else if (strcmp(word2[count], word1[x]) == 0)
            
                if (strcmp(word1[count], word2[x]) == 0)
                
                    //cerr << "Repeat rule" << endl;
                    repeat = true;
                
            
            else if (strcmp(word2[count], word2[x]) == 0)
            
                if (strcmp(word1[count], word1[x]) == 0)
                
                    //cerr << "Repeat rule" << endl;
                    repeat = true;
                
            
            if (repeat) //tests to see which distance is lesser, then sets that to 0
            
                //cerr << "Repeat testing" << endl;
                if (distance[count] < distance[x])
                
                    distance[count] = 0;
                
                else
                
                    distance[x] = 0;
                
            
            //cerr << "X:" << x << endl;
        
        //cerr << "Done with repeat" << endl;
        bool replace = false;
        if (distance[count] < 1) //non-positive distance check
        
            //cerr << "Bad distance: " << distance[count] << endl;
            replace = true;
        
        if (strlen(word1[count]) == 0 || strlen(word2[count]) == 0) //empty string check
        
            //cerr << "Empty string" << endl;
            replace = true;
        
        for (int charPos = 0; charPos < MAX_WORD_LENGTH; charPos++) //non-alphabetical check
        
            if (word1[count][charPos] != '\0' && word2[count][charPos] != '\0')
            
                if (!(isalpha(word1[count][charPos]) && isalpha(word2[count][charPos])))
                
                    //cerr << "Bad character 1: " << word1[count][charPos] << ", Bad character 2: " << word2[count][charPos] << endl;
                    replace = true;
                
            
        
        if (replace) //if bad rule, swaps current rule with last valid (or unchecked) rule
        
            //cerr << "Begin" << endl;
            for (int x = 0; x < validCheck; x++)
            
                //cerr << "Dist: " << distance[x] << ", word1: " << word1[x] << ", word2: " << word2[x] << endl;
            
            //cerr << endl;
            int distReplace = distance[validCheck - 1];
            distance[validCheck - 1] = distance[count];
            distance[count] = distReplace;
            char word1Rep[MAX_WORD_LENGTH + 1];
            char word2Rep[MAX_WORD_LENGTH + 1];
            strcpy(word1Rep, word1[validCheck - 1]);
            strcpy(word2Rep, word2[validCheck - 1]);
            strcpy(word1[validCheck - 1], word1[count]);
            strcpy(word2[validCheck - 1], word2[count]);
            strcpy(word1[count], word1Rep);
            strcpy(word2[count], word2Rep);
            for (int x = 0; x < validCheck; x++)
            
                //cerr << "Dist: " << distance[x] << ", word1: " << word1[x] << ", word2: " << word2[x] << endl;
            
            validCheck--;
            count--;
            //cerr << "End" << endl;
        
    
    for (int x = 0; x < validCheck; x++)
    
        //cerr << "Dist: " << distance[x] << ", word1: " << word1[x] << ", word2: " << word2[x] << endl;
    
    //cerr << "validCheck: " << validCheck << endl;
    return validCheck;


int determineQuality(const int distance[], const char word1[][MAX_WORD_LENGTH + 1], const char word2[][MAX_WORD_LENGTH + 1], int nRules, const char document[])

    //cerr << "Checkpoint A" << endl;
    int quality = 0; //counter for matches
    char words[200][200]; //array to hold all words in document
    int count = 0;
    int arrayPos = 0;
    while (count < strlen(document)) //loop through document
    
        //cerr << "Checkpoint B" << endl;
        int charPos = 0;
        while (count < strlen(document) && document[count] != ' ') //split document up into words and record words in array
        
            //cerr << "Checkpoint C: " << count << endl;
            if (isalpha(document[count]) && charPos < 200) //record only alphabetical characters
            
                words[arrayPos][charPos] = tolower(document[count]);
                charPos++;
            
            count++;
        
        count++;
        words[arrayPos][charPos] = '\0'; //end each word with a null byte
        //cerr << "Word: " << words[arrayPos] << endl;
        arrayPos++;
    
    for (int ruleCount = 0; ruleCount < nRules; ruleCount++) //compare rules to words
    
        bool match = false; //boolean to record if rule has a match or not
        for (int wordCount = 0; wordCount <= arrayPos; wordCount++)
        
            if (strcmp(word1[ruleCount], words[wordCount]) == 0) //if word1 finds a match, look for a match for word2 within distance
            
                int beginning = wordCount - distance[ruleCount];
                if (beginning < 0)
                
                    beginning = 0;
                
                int end = wordCount + distance[ruleCount];
                if (end >= arrayPos)
                
                    end = arrayPos;
                
                for (int arrayCheck = beginning; arrayCheck <= end; arrayCheck++)
                
                    if (strcmp(word2[ruleCount], words[arrayCheck]) == 0)
                    
                        match = true;
                    
                
            
            if (strcmp(word2[ruleCount], words[wordCount]) == 0) //if word2 find a match, look for a match for word1 within distance
            
                int beginning = wordCount - distance[ruleCount];
                if (beginning < 0)
                
                    beginning = 0;
                
                int end = wordCount + distance[ruleCount];
                if (end >= arrayPos)
                
                    end = arrayPos;
                
                for (int arrayCheck = beginning; arrayCheck <= end; arrayCheck++)
                
                    if (strcmp(word1[ruleCount], words[arrayCheck]) == 0)
                    
                        match = true;
                    
                
            
        
        if (match) //if rule had a match, increment quality
        
            quality++;
        
    
    return quality;

【问题讨论】:

使用 valgrind 并使用所有警告和调试信息 (gcc -Wall -Wextra -g) 编译您的代码。还可以使用调试器 (gdb),尤其是它的观察点。你可能在某处有一些undefined behavior! 显示你的源代码。看起来您错误地使用了strcpy(内存区域重叠)。考虑使用memmove。顺便说一句,在 C++ 中你应该使用 std::string 听起来像缓冲区溢出,这意味着您正在访问数组边界之外的数组索引。可能你刚刚在 Visual Studio 中走运了。不看代码有点难说。 尝试找出源代码中的违规部分,并在您的问题中添加MCVE。 请出示你的standardizeRules函数。 【参考方案1】:

感谢您的帮助。

经过进一步调查,我发现该错误是由于使用 strcpy() 与源地址相同。

【讨论】:

以上是关于如何修复 g++ 内存范围重叠?的主要内容,如果未能解决你的问题,请参考以下文章

如何确定Javascript中项目网格中的选择范围之间的重叠

如何修复 strcpy 以便检测重叠字符串

如何修复重叠的片段

如何修复 iOS 7 中的状态栏重叠问题

如何修复表格视图的搜索栏与状态栏重叠

PHP:选择时间范围重叠日期的重叠日期时间范围