尝试创建一个循环连接两个字符串的程序,打印出字母表。当我达到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);
答案 0 :(得分:3)
char* new = malloc(sizeof(char))
分配长度为1的缓冲区。
然后你将一个char(%c)sprintf到该缓冲区,这需要2个字节(char和终止零),因此缓冲区溢出和内存损坏。
答案 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
可能会有更多,但你明白了。