我的C代码存在一些问题。
该代码旨在读取特定类型的txt文件(它通过相似性在基本搜索引擎的C项目中使用,可以搜索图像,音频或文本文件)。
以下是代码:
typedef struct HISTOGRAMME_E{
int ** valeurs;
int nbcolonne;
int nbligne;
char type;
}HISTOGRAMME;
HISTOGRAMME * lireDescripteur(FILE * read){
HISTOGRAMME * retour = malloc(sizeof(HISTOGRAMME));
int etat = 0;
int id, type, nbligne, nbcolonne;
unsigned int max;
unsigned int cpt = 0;
int i;
char canswitch = 1;
char* val = malloc(sizeof(char));
int ** histoTempo;
while (fscanf(read,"%s",val) == 1) {
// Fonctionnement en MAE
// Actions
if(etat == 1){
id = atoi(val);
etat = 0;
}
if(etat == 2){
if(strcmp(val, "RGB"))
type = 3;
else
type = 1;
etat = 0;
}
if(etat == 3){
nbcolonne = atoi(val);
etat = 0;
}
if(etat == 4){
nbligne = atoi(val);
etat = 0;
}
// Valeurs
if(etat == 5){
max = nbligne * nbcolonne;
histoTempo = malloc(sizeof(int*)*2);
histoTempo[0] = malloc(sizeof(int)*max);
histoTempo[1] = malloc(sizeof(int)*max);
cpt = 0;
canswitch = 0;
histoTempo[0][0] = (int)strtol(val, NULL, 0);
etat = 52;
}
if(etat == 51 && canswitch){
histoTempo[0][cpt] = (int)strtol(val, NULL, 0);
etat = 52;
canswitch = 0;
}
if(etat == 52 && canswitch){
histoTempo[1][cpt] = atoi(val);
etat = 51;
canswitch = 0;
cpt += 1;
}
// Changement d'états
if(strcmp(val, "<id>") == 0 && (etat == 0))
etat = 1;
if(strcmp(val, "<type>") == 0 && (etat == 0))
etat = 2;
if(strcmp(val, "<nbcolonne>") == 0 && (etat == 0))
etat = 3;
if(strcmp(val, "<nbligne>") == 0 && (etat == 0))
etat = 4;
if(strcmp(val, "<valeurs>") == 0 && (etat == 0))
etat = 5;
//if(strcmp(val, "</valeurs>") == 0 && ((etat==51) || (etat == 52)))
if(strcmp(val, "</valeurs>") == 0)
{
//affichage debug
printf("id:%u, type:%u, nbcolonne:%u, nbligne:%u\n", id, type, nbcolonne,nbligne);
/*for(i=0;i<cpt;i++){
printf("%x : %u \n", histoTempo[0][i], histoTempo[1][i]);
}*/
int ** histogramme = malloc(sizeof(int*)*2);
histogramme[0] = malloc(sizeof(int)*cpt);
histogramme[1] = malloc(sizeof(int)*cpt);
for(i=0;i<cpt;i++){
histogramme[0][cpt] = histoTempo[0][cpt];
histogramme[1][cpt] = histoTempo[1][cpt];
}
cpt = 0;
etat = 0;
retour->valeurs = histogramme;
retour->nbcolonne = nbcolonne;
retour->nbligne = nbligne;
retour->type = type;
nbligne = 0;
nbcolonne = 0;
type = 0;
free(histoTempo[0]);
free(histoTempo[1]);
free(histoTempo);
free(val);
return retour;
}
canswitch =1;
}
return retour;
}
void test()
{
FILE * read = fopen(FICHIER_DESCRIPTEUR,"r");
HISTOGRAMME * test;
int i = 0;
test = lireDescripteur(read);
//printf("%i\n\n\n", test->valeurs[1][1]);
fclose(read);
free(test);
}
这是Valgrind的日志:
> 220 bytes in 1 blocks are indirectly lost in loss record 1 of 3
>> ==21968== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
>> ==21968== by 0x402AF2: lireDescripteur (index_img.c:905)
>> ==21968== by 0x402C62: test (index_img.c:942)
>> ==21968== by 0x402C8F: main (index_img.c:958)
> ==21968== 220 bytes in 1 blocks are indirectly lost in loss record 2 of 3
>> ==21968== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
>> ==21968== by 0x402B13: lireDescripteur (index_img.c:906)
>> ==21968== by 0x402C62: test (index_img.c:942)
>> ==21968== by 0x402C8F: main (index_img.c:958)
> ==21968== 456 (16 direct, 440 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 3
>> ==21968== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
>> ==21968== by 0x402ADF: lireDescripteur (index_img.c:904)
>> ==21968== by 0x402C62: test (index_img.c:942)
>> ==21968== by 0x402C8F: main (index_img.c:958)
它似乎是来自&#34; histogramme&#34;的malloc。 in&#34; lireDescripteur&#34;但我无法理解为什么。 (valgrind指出的三行代码:)
int ** histogramme = malloc(sizeof(int*)*2);
histogramme[0] = malloc(sizeof(int)*cpt);
histogramme[1] = malloc(sizeof(int)*cpt);
该功能&#34; lireDescripteur&#34;应该在类型&#34; HISTOGRAMME&#34;的结构上返回一个指针,用它的&#34; valeurs&#34;指向&#34; histogramme&#34;。
答案 0 :(得分:4)
valgrind指出的问题似乎超出了你所展示的代码,但是在你展示的代码中,你也有内存泄漏,因为你没有在所有返回路径中释放val
:这里:
canswitch =1;
}
return retour; // you're not freeing `val` here
但更重要的是,您有未定义的行为,因为val
是一个1字节的数组,并且您正在为其添加更多数据(请参阅:How dangerous is it to access an array out of bounds?)。
我建议使用一个正确大小的本地数组(如果你有更大的单词则增加):
char val[100];
int ** histoTempo;
while (fscanf(read,"%99s",val) == 1) { // safe fscanf: cannot read more than 99 chars
最后不要free(val)
。这样你就可以解决内存泄漏和可能导致程序崩溃的内存泄漏。
(您的程序有几次这个问题,来自您提供的链接。作为一般规则,当您不需要将缓冲区返回给调用者时,请使用正确大小的本地数组)