2013-08-01 35 views
2

當我嘗試運行我的代碼時,它在第89行的malloc上導致了分段錯誤:「s1 = malloc(65536);」即使我將其更改爲釋放calloc或realloc其持續存在,這也導致該寫入,如果我有我的函數來釋放內存上線82或86:代碼在分配內存時導致分段錯誤或釋放內存時中止程序

*** glibc detected *** /home/purlox/whaat: free(): invalid next size (normal): 0x00000000017b32b0 *** 
======= Backtrace: ========= 
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7ff4f61aeb96] 
/home/purlox/whaat[0x400904] 
/home/purlox/whaat[0x4024de] 
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ff4f615176d] 
/home/purlox/whaat[0x400699] 
======= Memory map: ======== 
00400000-00404000 r-xp 00000000 00:15 524713        /home/purlox/whaat 
00603000-00604000 r--p 00003000 00:15 524713        /home/purlox/whaat 
00604000-00605000 rw-p 00004000 00:15 524713        /home/purlox/whaat 
01793000-017b4000 rw-p 00000000 00:00 0         [heap] 
7ff4f5f18000-7ff4f5f2d000 r-xp 00000000 08:05 4066792     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7ff4f5f2d000-7ff4f612c000 ---p 00015000 08:05 4066792     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7ff4f612c000-7ff4f612d000 r--p 00014000 08:05 4066792     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7ff4f612d000-7ff4f612e000 rw-p 00015000 08:05 4066792     /lib/x86_64-linux-gnu/libgcc_s.so.1 
7ff4f6130000-7ff4f62e5000 r-xp 00000000 08:05 4067023     /lib/x86_64-linux-gnu/libc-2.15.so 
7ff4f62e5000-7ff4f64e4000 ---p 001b5000 08:05 4067023     /lib/x86_64-linux-gnu/libc-2.15.so 
7ff4f64e4000-7ff4f64e8000 r--p 001b4000 08:05 4067023     /lib/x86_64-linux-gnu/libc-2.15.so 
7ff4f64e8000-7ff4f64ea000 rw-p 001b8000 08:05 4067023     /lib/x86_64-linux-gnu/libc-2.15.so 
7ff4f64ea000-7ff4f64ef000 rw-p 00000000 00:00 0 
7ff4f64f0000-7ff4f6512000 r-xp 00000000 08:05 4067008     /lib/x86_64-linux-gnu/ld-2.15.so 
7ff4f6712000-7ff4f6713000 r--p 00022000 08:05 4067008     /lib/x86_64-linux-gnu/ld-2.15.so 
7ff4f6713000-7ff4f6715000 rw-p 00023000 08:05 4067008     /lib/x86_64-linux-gnu/ld-2.15.so 
7ff4f6715000-7ff4f671b000 rw-p 00000000 00:00 0 
7fffa991c000-7fffa993f000 rw-p 00000000 00:00 0       [stack] 
7fffa9a00000-7fffa9a01000 r-xp 00000000 00:00 0       [vdso] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
Aborted (core dumped) 

GDB說,「自由(STR->串);」造成的,但我不知道如何。分配內存的錯誤只發生在一個特定的地方,我嘗試改變分配給內存的大小,使其大於或小於現在的分配內存大小(例如,我嘗試只分配8個字節,或者嘗試了像現在那樣分配100次),但它仍然導致了相同的分段錯誤。

whaat.c

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

int main(void) { 
    char* s1, 
       s2; 

// 12 byte long strings 
    char s3[8] = "Nequeou", 
      s4[8] = "quisqua"; 

// 256 byte long strings 
    char s5[256] = "Pellentesque venenatis rhoncus urna id tincidunt. Quisque blandit rhoncus nisi, vel facilisis odio ornare nec. Maecenas id tellus sit amet nunc auctor commodo. Proin egestas molestie malesuada. Vestibulum in lacus quis nisl ultricies cursus non ac nullam.", 
      s6[256] = "Sed tristique porta lorem. Ut elementum est in magna laoreet, in lacinia ante blandit. Vestibulum condimentum sem vel ligula feugiat, vel venenatis ante placerat. Phasellus nec turpis viverra sapien vehicula sagittis vitae tincidunt lectus. Fusce posuere."; 

// 65 536 byte long strings 
    char s7[65536], 
      s8[65536]; 

    s_string ss1, 
        ss2, 

        ss3, 
        ss4, 

        ss5, 
        ss6, 

        ss7, 
        ss8; 

    FILE *LoremIpsum; 
    int i; 

    s_init(&ss3, "Nequeou ", 8); 
    s_init(&ss4, "quisqua ", 8); 
    s_init(&ss5, "Pellentesque venenatis rhoncus urna id tincidunt. Quisque blandit rhoncus nisi, vel facilisis odio ornare nec. Maecenas id tellus sit amet nunc auctor commodo. Proin egestas molestie malesuada. Vestibulum in lacus quis nisl ultricies cursus non ac nullam. ", 256); 
    s_init(&ss6, "Sed tristique porta lorem. Ut elementum est in magna laoreet, in lacinia ante blandit. Vestibulum condimentum sem vel ligula feugiat, vel venenatis ante placerat. Phasellus nec turpis viverra sapien vehicula sagittis vitae tincidunt lectus. Fusce posuere. ", 256); 
    s_init(&ss7, NULL, 65536); 
    s_init(&ss8, NULL, 65536); 

    LoremIpsum = fopen("Lorem ipsum", "r"); 
    if(LoremIpsum == NULL) { 
     perror("Error opening file "); 
     return 1; 
    } 

    fgets(s7, 65536, LoremIpsum); 
    fgets(s8, 65536, LoremIpsum); 
    fgets(ss7.string, 65536, LoremIpsum); 
    ss7.string[65535] = ' '; 
    fgets(ss8.string, 65536, LoremIpsum); 
    ss8.string[65535] = ' '; 

    if(fclose(LoremIpsum) == EOF) { 
     perror("Error closing file "); 
     return 2; 
    } 

    s1 = malloc(8); 
    strcpy(s1, ""); 
    strcat(s1, s3); 
    free(s1); 

    s_init(&ss1, NULL, 8); 
    s_strcat(&ss1, &ss3); 
    s_free(&ss1); 

    s_init(&ss1, NULL, 8); 
    s_strcat2(&ss1, &ss3); 
    s_free(&ss1); 


    s1 = malloc(256); 
    strcpy(s1, ""); 
    strcat(s1, s5); 
    free(s1); 

    s_init(&ss1, NULL, 256); 
    s_strcat(&ss1, &ss5); 
    s_free(&ss1); 

    s_init(&ss1, NULL, 256); 
    s_strcat2(&ss1, &ss5); 
    s_free(&ss1); 


    s1 = malloc(65536); 
    strcpy(s1, ""); 
    strcat(s1, s7); 
    free(s1); 

    s_init(&ss1, NULL, 65536); 
    s_strcat(&ss1, &ss7); 
    s_free(&ss1); 

    s_init(&ss1, NULL, 65536); 
    s_strcat2(&ss1, &ss7); 
    s_free(&ss1); 

    s_free(&ss3); 
    s_free(&ss4); 
    s_free(&ss5); 
    s_free(&ss6); 
    s_free(&ss7); 
    s_free(&ss8); 

    return 0; 
} 

sstring.h

#include <stdlib.h> 

typedef struct { 
    unsigned int length; 
    char *string; 
} s_string; 

s_string *s_init(s_string *str, char *array, size_t num) { 
    int i; 

    if(str == NULL) 
     str = malloc(sizeof(s_string)); 

    if(array == NULL) { 
     str->length = num; 

     if(num != 0) 
      str->string = malloc(num); 
     else 
      str->string = NULL; 
    } else { 
     if(num == 0) { 
      str->string = NULL; 

      for(i = 0; array[i] != '\0'; i++) { 
       str->string = realloc((void *)(str->string), i + 1); 
       str->string[i] = array[i]; 
      } 

      str->length = i; 
     } else { 
      str->string = malloc(num); 

      str->length = num; 

      for(i = 0; i < num; i++) 
       str->string[i] = array[i]; 
     } 
    } 

    return str; 
} 

void s_free(s_string* str) { 
    if(str != NULL && str->string != NULL) { 
    free(str->string); 
    str->length = 0; 
    } 
} 

s_string *s_strcat(s_string *destination, const s_string *source) { 
    int i, 
      j; 

    for(i = destination->length, j = 0; j < source->length; i++, j++) 
     destination->string[i] = source->string[j]; 

    destination->length += source->length; 

    return destination; 
} 

// second version 
s_string *s_strcat2(s_string *destination, const s_string *source) { 
    int i; 

    for(i = 0; i < source->length; i++) 
     destination->string[i + destination->length] = source->string[i]; 

    destination->length += source->length; 

    return destination; 
} 

回答

4

考慮與s_strcat()你的第一個測試:

s_init(&ss1, NULL, 8); 
    s_strcat(&ss1, &ss3); 

截至結束,ss1用分配給8字節的存儲器進行初始化。

if(array == NULL) { 
     str->length = num; 

     if(num != 0) 
      str->string = malloc(num); 

然而,s_strcat()實現去分配內存的末尾,然後複製ss3數據:

for(i = destination->length, j = 0; j < source->length; i++, j++) 
     destination->string[i] = source->string[j]; 

到環編寫超出你的分配內存的結束,破壞堆數據結構由malloc()和朋友使用。

s_strcat2()有一個類似的問題,寫入超出destination->length,它代表分配的內存的大小。

for(i = 0; i < source->length; i++) 
     destination->string[i + destination->length] = source->string[i]; 

您可以利用的內存調試工具,如valgrind更容易調試像這樣的問題。 valgrind可幫助您識別軟件中存在與內存相關的錯誤的代碼行,例如寫入未分配的內存,在分配的內存之外進行寫入以及釋放未分配的內存。

+1

提及內存調試器如valgrind會使這個答案完美。 +1從我:) – Sebivor

+0

@undefinedbehaviour:啊,完美。答覆更新,謝謝。 – jxh

+0

謝謝,我沒有意識到這一點,因爲我認爲源的長度總是較小,這並不一定是真實的,但即使在s_strcat和s_strcat2中檢查了兩個長度之後,它仍然會導致與之前一樣的錯誤,所以我不認爲這是問題所在。 我會嘗試valgrid,看看它是否可以幫助我找到問題。 –