setlocale(LC_ALL,"pt_PT.UTF-8");
FILE *vocabulario = fopen(*(++argv),"r");
FILE *original = fopen(*(++argv),"r");
FILE *convertido = fopen(*(++argv),"w");
if (vocabulario == NULL || original == NULL || convertido == NULL){
printf("Não foi possível abrir um dos ficheiros");
return 1;
}
char delimitador = '\t';
TNode * root = NULL;
Conversor * temp = NULL;
char linhaLida[BUFFER];
char linhaTemp[BUFFER];
char linhaEscrever[BUFFER];
int i = 0;
while(fgets(linhaLida,BUFFER,vocabulario) != NULL){
if ( !criarConversor(&temp,linhaLida,delimitador) ) continue;
insertNodeViciado(&root,temp);
i++;
}
/* criarConversor implementation*/
20 int criarConversor(Conversor ** temp,char * stringAUsar,char delimitador){
21 int contador = obterNumeroDelimitadores(stringAUsar,delimitador);
22 char delimitadorInterno[] = {delimitador,'\n'};
23 if (contador == 0) return 0;
24 *temp = malloc(sizeof(Conversor));
25 verificarAlocacao(*temp);
26 (*temp)->original = obterStringAlocada(stringAUsar,delimitadorInterno);
27 if (contador == 1){
28 (*temp)->preferencia = obterStringAlocada(NULL,delimitadorInterno);
29 (*temp)->opcoes = NULL;
30 } else {
31 (*temp)->preferencia = NULL;
32 (*temp)->opcoes = malloc((contador+1)*sizeof(char *));
33 verificarAlocacao((*temp)->opcoes);
34 int i = 0;
35 while(i<contador) *(((*temp)->opcoes)+i++) = obterStringAlocada(NULL,delimitadorInterno);
36 *(((*temp)->opcoes)+i) = NULL;
}
37 return 1;
typedef struct conversor{
char * original;
char * preferencia;
char ** opcoes;
} Conversor;
Conditional jump or move depends on uninitialised value(s)
==2306== at 0x40AB01E: strtok (strtok.S:165)
==2306== by 0x8048E1E: criarConversor (Conversor.c:35)
==2306== by 0x8048984: main (main.c:24)
==2306== Uninitialised value was created by a stack allocation
==2306== at 0x8048D18: criarConversor (Conversor.c:20)
/*Gets the token,checks to see if there was a token,allocates on the heap and returns the pointer to the heap allocated string*/
char * obterStringAlocada(char * string,char * delimitador){
char * token = strtok(string,delimitador);
verificarAlocacao(token);
char * alocada = strcpy(malloc(strlen(token)+1),token);
return alocada;
}
/*Counts how many delimiters there is on the string*/
int obterNumeroDelimitadores(char * string,char delimitador){
int contador = 0;
int i = 0;
while (*(string+i) != '\0') if (*(string+i++) == delimitador)contador++;
return contador;
}
/* checks if the memory was properly allocated,which why its always called after malloc*/
void verificarAlocacao(void * verificar){
if (verificar == NULL){
printf("Não foi possível alocar a memória necessária\nO programa vai encerrar");
exit(1);
}
}
Valgrind给我的未初始化值是由criarConversor()实现中的堆栈分配创建的。
我的问题是:价值如何未初始化? delimitador是一个变量,其他两个变量。我能理解是否有人说linhaLida没有被初始化,除非代码永远不会到达if(!criarConversor()),除非linhaLida是由fgets函数编写的。
答案 0 :(得分:6)
问题在于:
char delimitadorInterno[] = {delimitador,'\n'};
// ...
char * token = strtok(string,delimitador);
strtok
的第二个参数应该指向字符串,它是要查找的分隔符。但是,您传递了一个指向两个不形成字符串的字符的指针,从而导致valgrind在strtok
读取超过'\ n'时捕获的未定义行为。
要解决此问题,请更改为:
char delimitadorInterno[] = { delimitador,'\n', 0 };
或者
char delimitadorInterno[] = { delimitador, 0 };
我猜你打算只使用分隔符作为分隔符(而不是分隔符的序列,后跟换行符)。由于fgets
的结果最后只能有换行符,因此带\n
的版本永远不会匹配任何内容,除非该行以分隔符结尾,在这种情况下它将匹配一次。