分配内存时代码导致分段错误或释放内存时中止程序

The*_*Fox 2 c free memory-management segmentation-fault

当我尝试运行代码时,它会导致第 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)
Run Code Online (Sandbox Code Playgroud)

gdb 表示“free(str->string);” 造成的,但我不确定是怎么造成的。分配内存的错误仅发生在一个特定位置,我尝试将分配的内存大小更改为比现在更多或更少(例如,我尝试仅分配 8 个字节,或者我尝试分配现在的 100 倍),但它仍然导致相同的分段错误。

何特.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;
}
Run Code Online (Sandbox Code Playgroud)

字符串.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;
}
Run Code Online (Sandbox Code Playgroud)

jxh*_*jxh 5

考虑您的第一个测试s_strcat()

    s_init(&ss1, NULL, 8);
    s_strcat(&ss1, &ss3);
Run Code Online (Sandbox Code Playgroud)

在 的末尾s_init()ss1使用分配 8 个字节的内存进行初始化。

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

        if(num != 0)
            str->string = malloc(num);
Run Code Online (Sandbox Code Playgroud)

但是,s_strcat()实现的是转到已分配内存的末尾,并从以下位置复制数据ss3

    for(i = destination->length, j = 0; j < source->length; i++, j++)
        destination->string[i] = source->string[j];
Run Code Online (Sandbox Code Playgroud)

该循环正在超出分配的内存末尾进行写入,从而损坏了malloc()和 朋友使用的堆数据结构。

s_strcat2()有类似的问题,写 Beyond destination->length,它代表分配的内存的大小。

    for(i = 0; i < source->length; i++)
        destination->string[i + destination->length] = source->string[i];
Run Code Online (Sandbox Code Playgroud)

您可以使用内存调试工具(例如valgrind. valgrind可以帮助您识别软件中存在内存相关错误的代码行,例如写入未分配的内存、写入超出分配的内存以及释放未分配的内存。