未初始化的值由堆栈分配valgrind C创建

时间:2014-07-13 23:17:45

标签: c

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函数编写的。

1 个答案:

答案 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的版本永远不会匹配任何内容,除非该行以分隔符结尾,在这种情况下它将匹配一次。