尝试free()时程序崩溃

时间:2014-03-26 22:27:00

标签: c gdb

尝试创建一个循环连接两个字符串的程序,打印出字母表。当我达到11时,我在尝试释放(新)时会出错。

#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main(void)
{
    char* word = NULL;


    for(int i = 0; i < 25; i++)
    {       
        int buff = 'a' + i;

        // creates first string
        if (i == 0)
        {
            char* new = malloc(sizeof(char) + 1);
            if (new == NULL)
            {
                printf("malloc failed");
                return 1;
            }
            sprintf(new, "%c", buff);
            word = (char *) malloc(sizeof(new));
            if (word == NULL)
            {
                printf("malloc failed");
                return 1;
            }
            *word = *new;
            free(new);
        }
        // adds string word to string new
        else
        {
            char* new = malloc(sizeof(char) + 1);
            if (new == NULL)
            {
                printf("malloc failed");
                return 1;
            }
            sprintf(new, "%c", buff);
            char* new_word = malloc(strlen(word) + strlen(new) + 1);
            if (new_word == NULL)
            {
                printf("malloc failed");
                return 1;
            }
            // Copies combines word and new into new_word
            strcpy(new_word, word);
            strcat(new_word, new);

            // Resizes memory for word and prints new_word into word
            word = (char *) realloc(word, strlen(new_word));
            sprintf(word, "%s", new_word);
            // Frees looped vars
            free(new);
            free(new_word);
        }

        printf("%s\n", word);
    }
}

这是我得到的结果:

a
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
abcdefghijk
*** Error in `./test': free(): invalid pointer: 0x08cac028 ***

这是我在尝试调试时从GDB获得的内容:

(gdb) 
56              free(new);
(gdb) info locals
new = 0x804b008 "l"
new_word = 0x804b038 "abcdefghijkl"
buff = 108
i = 11
word = 0x804b018 "abcdefghijkl"
(gdb) n
*** Error in `/home/jharvard/Dropbox/pset6/test': invalid fastbin entry (free): 0x0804b008 ***

Program received signal SIGSEGV, Segmentation fault.
0x4408e098 in malloc_consolidate (av=av@entry=0x441d4420 <main_arena>)
    at malloc.c:4093
4093              unlink(av, nextchunk, bck, fwd);

2 个答案:

答案 0 :(得分:3)

char* new = malloc(sizeof(char))分配长度为1的缓冲区。 然后你将一个char(%c)sprintf到该缓冲区,这需要2个字节(char和终止零),因此缓冲区溢出和内存损坏。

如果完全没有效率且基本无用,BTW会分配非常小的缓冲区。您可能应该从头开始重新考虑您的计划。

答案 1 :(得分:1)

C中的字符串必须始终在末尾具有空终止符(也称为“\ 0”)。 null终止符标记字符串的结尾。如果没有null终止符,许多C字符串库函数将运行超过字符串的结尾,如果幸运的话会导致崩溃。如果你运气不好,超过一个字符串的末尾将破坏与该字符串无关的数据,导致极难找到的错误。 strlen函数计算字符串中的字符数,但该计数包含空终止符。

char *new = malloc(sizeof(char));                      // returns a pointer to 1 byte of memory.
sprintf(new, "%c", buff);                              // writes two characters into that memory, whatever buff is, and a null terminator '\0'
*word = *new;                                          // copies the first character of 'new' into 'word', but doesn't null terminate 'word'
word = (char *) malloc(sizeof(new));                   // since new is a pointer, sizeof(new) is the size of a pointer, 4 bytes on 32-bit systems, 8 bytes on 64-bit systems
char* new_word = malloc(strlen(word) + strlen(new));   // allocates enough space for the two string but doesn't include space for the null terminator
word = (char *) realloc(word, strlen(new_word));       // again no space for the null terminator

可能会有更多,但你明白了。