मैं उस निर्देशिका का पथ खोलने के लिए opendir(.) का उपयोग करता हूं जिसे मैं पढ़ना चाहता हूं। मैं तब readdir लूप के साथ वर्तमान निर्देशिका में सभी फाइलों और निर्देशिकाओं के माध्यम से जाने के लिए उपयोग करता हूं। मेरे पास रीडडिर की सामग्री को स्टोर करने के लिए char** सूची है। मैं फिर **list को लेक्सिग्राफिक क्रम में रखने के लिए एक सॉर्ट करता हूं। जब मेरे पास 63 से अधिक वर्णों की लंबाई वाली फ़ाइल होती है, तो केवल आउटपुट को सॉर्ट करते समय मुझे एक अतिप्रवाह त्रुटि मिलती रहती है। ऐसा क्यों है और मैं इसे कैसे ठीक कर सकता हूं?

void ls_short() {
    char **list = NULL;
    int count = 0;
    DIR  *dir;
    struct dirent *rd;
    dir = opendir(".");
    // check to make sure that we can open the directory
    if(dir == NULL){
        perror("Not able to open The current directory.");
        exit(EXIT_FAILURE);
    }
    
    while((rd = readdir(dir)) != NULL){
        list = realloc(list, (count+1)*sizeof(*list));
        list[count] = rd ->d_name;
        ++count;
        printf("%s\n",rd ->d_name);
    }
    printf("here we will print the list\n");
    for (int i = 0; i < count;i++){
        printf("%s\n",list[i]);
    }
    printf("Now we print the list in order and also get rid of . and .. directory\n");
    list = realloc(list, (count+1)*sizeof(*list));
    list[count] = "";
    for (int i = 0; i < count - 1; i++){
        for (int j = 0; j < count - i - 1; j++){
            if (strcasecmp(list[j], list[j + 1]) > 0) {
                    char* temp;
                    temp = (char*)calloc(count, sizeof(char)*256);
                    strcpy(temp, list[j]);
                    strcpy(list[j], list[j + 1]);
                    strcpy(list[j + 1], temp);
                    free(temp);
            }
        }
    }
    for (int i = 2; i < count;i++){
        printf("%s\n",list[i]);
    }
    closedir(dir);
}

यह त्रुटि है जो मुझे मिल रही है:

screenshot of error messages

=================================================================
==43335==ERROR: AddressSanitizer: strcpy-param-overlap: memory ranges [0x6250000001fd,0x625000000220) and [0x62500000021d, 0x625000000240) overlap
    #0 0x103ef03ef in wrap_strcpy+0xaf (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef)
    #1 0x103e9aa5d in ls_short ls.c:61
    #2 0x103e9a5c4 in main ls.c:16
    #3 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)

0x6250000001fd is located 253 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
    #0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
    #1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
    #2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
    #3 0x103e9a6ad in ls_short ls.c:42
    #4 0x103e9a5c4 in main ls.c:16
    #5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)

0x62500000021d is located 285 bytes inside of 8192-byte region [0x625000000100,0x625000002100)
allocated by thread T0 here:
    #0 0x103ef54c0 in wrap_malloc+0xa0 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x484c0)
    #1 0x7fff2025b0fe in _readdir_unlocked$INODE64+0x6d (libsystem_c.dylib:x86_64+0x2a0fe)
    #2 0x7fff2025b227 in readdir$INODE64+0x22 (libsystem_c.dylib:x86_64+0x2a227)
    #3 0x103e9a6ad in ls_short ls.c:42
    #4 0x103e9a5c4 in main ls.c:16
    #5 0x7fff20379620 in start+0x0 (libdyld.dylib:x86_64+0x15620)

SUMMARY: AddressSanitizer: strcpy-param-overlap (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x433ef) in wrap_strcpy+0xaf
==43335==ABORTING
Abort trap: 6
0
NoseNatchos 7 अक्टूबर 2021, 22:14
कृपया त्रुटि को सादे पाठ के रूप में पोस्ट करें, स्क्रीनशॉट के रूप में नहीं।
 – 
Barmar
7 अक्टूबर 2021, 22:17
किसी भी कारण से आप बबल सॉर्ट बनाम केवल qsort का उपयोग कर रहे हैं?
 – 
ShadowRanger
7 अक्टूबर 2021, 22:26
मैंने त्रुटि को टेक्स्ट प्रारूप में पोस्ट किया है
 – 
NoseNatchos
7 अक्टूबर 2021, 23:09

2 जवाब

सबसे बढ़िया उत्तर

readdir() में rd->d_name के लिए एक स्थिर बफर है, जिसे वह हर बार कॉल करने पर पुन: उपयोग करता है, इसलिए आपके सभी list तत्व एक ही स्ट्रिंग की ओर इशारा कर रहे हैं।

जब आप उन्हें सरणी में असाइन करते हैं तो आपको स्ट्रिंग्स की एक प्रति बनानी चाहिए।

list[count] = strdup(rd->d_name);

और जब आप सॉर्ट कर रहे हों, तो स्ट्रिंग्स के बीच नामों की प्रतिलिपि न बनाएं, बस पॉइंटर्स को स्वैप करें।

            if (strcasecmp(list[j], list[j + 1]) > 0) {
                char* temp;
                temp = list[j];
                list[j] = list[j+1];
                list[j+1] = temp;
            }
1
Barmar 7 अक्टूबर 2021, 22:22
यह काम नहीं करेगा। यह केवल इस फ़ाइल नाम के लिए पर्याप्त मेमोरी आवंटित करता है। लेकिन उनके डिज़ाइन के लिए आवश्यक है कि प्रत्येक स्ट्रिंग बफ़र सबसे बड़ा फ़ाइल नाम रखने के लिए पर्याप्त बड़ा हो। (strcpy(list[j], list[j + 1]); जैसे कोड को देखें।)
 – 
David Schwartz
7 अक्टूबर 2021, 22:20
अच्छी पकड़। मैंने जोड़ा कि स्ट्रिंग्स को कॉपी करने के बजाय पॉइंटर्स को स्वैप करके इसे कैसे किया जाए।
 – 
Barmar
7 अक्टूबर 2021, 22:22
    while((rd = readdir(dir)) != NULL){
        list = realloc(list, (count+1)*sizeof(*list));
        list[count] = rd ->d_name;
        ++count;
        printf("%s\n",rd ->d_name);
    }

सूची में जो स्ट्रिंग आप जोड़ रहे हैं उसे पकड़ने के लिए आप कहीं भी स्मृति आवंटित नहीं करते हैं। आप इसे पॉइंटर रखने के लिए मेमोरी आवंटित करते हैं, लेकिन बस इतना ही।

आपको list[count] = rd ->d_name; को कुछ इस तरह बदलना होगा:

    list[count] = malloc(256);
    strcpy(list[count], rd->d_name);

साथ ही, जब आप सॉर्ट करते हैं तो आपको स्ट्रिंग्स के लिए नई मेमोरी आवंटित करने की आवश्यकता नहीं होती है। यदि आपके पास पहले से ही प्रत्येक स्ट्रिंग के लिए आवंटित स्मृति है जिसे आपको स्टोर करने की आवश्यकता है (जो आपको चाहिए या आपकी सूची पहले से ही टूटी हुई है), ऑर्डर बदलने के लिए स्ट्रिंग को पकड़ने के लिए नई मेमोरी आवंटित करने की आवश्यकता क्यों होगी?

0
David Schwartz 7 अक्टूबर 2021, 22:20
कोड की उन दो पंक्तियों ने इस मुद्दे को ठीक कर दिया। मैं बस उत्सुक हूं कि फ़ाइल नाम की लंबाई 63 से अधिक होने तक प्रोग्राम ठीक क्यों काम कर रहा था और मुझे strcpy का उपयोग क्यों करना है? इस प्रकार के लिए नई मेमोरी आवंटित करने के संबंध में क्या आप अस्थायी या सूची का जिक्र कर रहे हैं? आपके सहयोग के लिए धन्यवाद।
 – 
NoseNatchos
7 अक्टूबर 2021, 22:58