2

コードを実行しようとすると、「s1 = malloc(65536);」で 89 行目の malloc でセグメンテーション違反が発生します。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 は、「free(str->string);」それが原因でしたが、方法がわかりません。メモリの割り当てに関するエラーは特定の 1 つの場所でのみ発生し、割り当てられたメモリのサイズを現在よりも多かれ少なかれ変更しようとしました (たとえば、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

1 に答える 1

4

を使用した最初のテストの 1 つを検討してくださいs_strcat()

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

の最後でs_init()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];

などのメモリ デバッグ ツールを使用すると、このような問題をより簡単にデバッグできますvalgrindvalgrind未割り当てメモリへの書き込み、割り当て済みメモリを超えた書き込み、未割り当てメモリの解放など、メモリ関連のバグがあるソフトウェア内のコード行を特定するのに役立ちます。

于 2013-08-01T02:42:46.290 に答える