我想做一个小的自动完成程序。我从文件中取出字符串,并将它们逐行放入2D char类型数组中。
这是我的代码:
Dictionnary.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Dictionnary.h"
int getDictionnarySize(FILE *theDictionnary)
{
size_t pos = ftell(theDictionnary);
fseek(theDictionnary, 0, SEEK_END);
size_t len = ftell(theDictionnary);
fseek(theDictionnary, pos, SEEK_SET);
return (len);
}
int getNbLines(char *buff)
{
int lines = 1;
int i = 0;
while (buff[i] != ' ')
{
if (buff[i] == 'n')
lines++;
i++;
}
return (lines);
}
int allocDictionnary(t_dictionnary *d, char *buff)
{
d->lines = getNbLines(buff) - 1;
int i;
char str[2048];
int len;
rewind(d->dico);
d->dictionnary = malloc(sizeof(*d->dictionnary) * d->lines);
for (i = 0; i <= d->lines; i++)
{
memset(str, 0, 2048);
fgets(str, 256, d->dico);
len = strlen(str);
printf("len = %dn", len);
d->dictionnary[i] = malloc(sizeof(**d->dictionnary) * len);
if (d->dictionnary[i] == NULL)
return (1);
strcpy(d->dictionnary[i], str);
printf("String is : %sn", d->dictionnary[i]);
}
return (0);
}
int initDictionnary(t_dictionnary *d)
{
int size;
char *buff;
if ((d->dico = fopen(d->theDictionnary, "r")) != NULL)
{
size = getDictionnarySize(d->dico);
buff = malloc(size + 1);
fread(buff, size, 1, d->dico);
allocDictionnary(d, buff);
fclose(d->dico);
}
else
{
return (1);
}
free(buff);
return (0);
}
int killDictionnary(char **theDictionnary, int size)
{
int i = 0;
while (i <= size)
{
free(theDictionnary[i]);
i++;
}
free(theDictionnary);
return (0);
}
Dictionnary.h
#ifndef __DICTIONNARRY_H__
# define __DICTIONNARY_H___
/* STRUCTURES */
typedef struct s_dictionnary
{
const char *theDictionnary;
FILE *dico;
char **dictionnary;
int lines;
} t_dictionnary;
/* PROTOTYPES */
int getDictionnarySize(FILE *theDictionnary);
int allocDictionnary(t_dictionnary *d, char *buff);
int initDictionnary(t_dictionnary *dico);
int getNbLines(char *buff);
int killDictionnary(char **theDictionnary, int size);
#endif /* __DICTIONNARY_H__ */
c
#include <stdlib.h>
#include <stdio.h>
#include "Dictionnary.h"
int main(int ac, char **av)
{
t_dictionnary d;
d.theDictionnary = "./miniDico";
initDictionnary(&d);
killDictionnary(d.dictionnary, d.lines);
return (0);
}
当我编译时,我没有任何错误或警告。但是当我运行这个时,我得到:
*** Error in `./a.out': corrupted double-linked list: 0x0000000000f19550 ***
Valgrind result:
==4004== Memcheck, a memory error detector
==4004== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4004== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==4004== Command: ./a.out
==4004==
==4004== Conditional jump or move depends on uninitialised value(s)
==4004== at 0x40095C: getNbLines (Dictionnary.c:22)
==4004== by 0x40098B: allocDictionnary (Dictionnary.c:34)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
len = 35
==4004== Invalid write of size 1
==4004== at 0x4C2D623: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x400AB8: allocDictionnary (Dictionnary.c:50)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004== Address 0x51d8723 is 0 bytes after a block of size 35 alloc'd
==4004== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x400A61: allocDictionnary (Dictionnary.c:47)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
==4004== Invalid read of size 1
==4004== at 0x4E7E1C2: vfprintf (in /usr/lib/libc-2.21.so)
==4004== by 0x4E84E38: printf (in /usr/lib/libc-2.21.so)
==4004== by 0x400AE5: allocDictionnary (Dictionnary.c:51)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004== Address 0x51d8723 is 0 bytes after a block of size 35 alloc'd
==4004== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x400A61: allocDictionnary (Dictionnary.c:47)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
String is : Paris, 458 boulevard Saint-Germain
len = 35
String is : Paris, 343 boulevard Saint-Germain
len = 44
String is : Marseille, 343 boulevard Camille Flammarion
len = 37
String is : Marseille, 29 rue Camille Desmoulins
len = 34
String is : Marseille, 1 chemin des Aubagnens
len = 25
String is : Paris, 12 rue des singes
len = 24
String is : Paris, 34 quai VoLtAiRe
len = 23
String is : Paris, 34 rue Voltaire
len = 33
String is : Lille, 120 boulevard Victor Hugo
len = 27
String is : Marseille, 50 rue Voltaire
len = 26
String is : Toulouse, 90 rue Voltaire
len = 30
String is : Strasbourg 84 rue du Bouclier
len = 42
String is : Marseille, 78 boulevard de la libération
len = 27
String is : Lille, 30 rue Victor Danel
len = 38
String is : Mont Saint Martin, 42 rue de Bordeaux
len = 47
String is : Mont de Marsan, 100 avenue Pierre de Coubertin
len = 35
String is : Strasbourg, 391 boulevard de Nancy
len = 38
String is : Lyon, 56 rue du Docteur Albéric Pont
len = 35
String is : Lyon, rue du Docteur Albéric Pont
len = 38
String is : 56 rue du Docteur Albéric Pont, Lyon
len = 19
String is : Lyon 56 grande rue
len = 24
String is : Lille, 90 rue d’Arras
len = 35
String is : Lille, 76 impasse Georges Pompidou
len = 25
==4004== Invalid write of size 8
==4004== at 0x400A62: allocDictionnary (Dictionnary.c:47)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004== Address 0x51d86b8 is 0 bytes after a block of size 184 alloc'd
==4004== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x4009C3: allocDictionnary (Dictionnary.c:40)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
==4004== Invalid read of size 8
==4004== at 0x400A7D: allocDictionnary (Dictionnary.c:48)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004== Address 0x51d86b8 is 0 bytes after a block of size 184 alloc'd
==4004== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x4009C3: allocDictionnary (Dictionnary.c:40)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
==4004== Invalid read of size 8
==4004== at 0x400AA4: allocDictionnary (Dictionnary.c:50)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004== Address 0x51d86b8 is 0 bytes after a block of size 184 alloc'd
==4004== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x4009C3: allocDictionnary (Dictionnary.c:40)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
==4004== Invalid read of size 8
==4004== at 0x400AD1: allocDictionnary (Dictionnary.c:51)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004== Address 0x51d86b8 is 0 bytes after a block of size 184 alloc'd
==4004== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x4009C3: allocDictionnary (Dictionnary.c:40)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
String is : Lyon, 2 allée des fleurs
==4004== Invalid read of size 8
==4004== at 0x400BF6: killDictionnary (Dictionnary.c:85)
==4004== by 0x400C53: main (main.c:11)
==4004== Address 0x51d86b8 is 0 bytes after a block of size 184 alloc'd
==4004== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4004== by 0x4009C3: allocDictionnary (Dictionnary.c:40)
==4004== by 0x400B9F: initDictionnary (Dictionnary.c:67)
==4004== by 0x400C42: main (main.c:10)
==4004==
==4004==
==4004== HEAP SUMMARY:
==4004== in use at exit: 0 bytes in 0 blocks
==4004== total heap usage: 27 allocs, 27 frees, 2,289 bytes allocated
==4004==
==4004== All heap blocks were freed -- no leaks are possible
==4004==
==4004== For counts of detected and suppressed errors, rerun with: -v
==4004== Use --track-origins=yes to see where uninitialised values come from
==4004== ERROR SUMMARY: 54 errors from 8 contexts (suppressed: 0 from 0)
可能这个循环造成了麻烦:
for (i = 0; i <= d->lines; i++)
似乎应该是(我已经改变了停止条件):
for (i = 0; i < d->lines; i++)
否则写在已分配空间后面…
澄清:
用d->dictionnary = malloc(sizeof(*d->dictionnary) * d->lines);
分配数组给你一个恰好包含d->lines
元素的数组。从0
索引开始,最后一个元素可以用d->lines-1
索引访问。所以当你使用从0
到d->lines
的循环时,最后一个循环循环将写在数组边界之外(即到d->lines
索引)。这就是你堕落的地方。通常情况下,C运行时不会检查此类错误,您只会在极少数情况下看到它们,并且可能远离导致它们的代码。
"损坏的链表"是关于堆损坏的。使用malloc
分配的块通常链接到链表中(这实际上取决于您的内存分配器的实现)。因此,当在分配边界之外编写代码时,您可能会破坏这个列表。