【问题标题】:Uninitialised value was created by a stack allocation valgrind C未初始化的值是由堆栈分配 valgrind C 创建的
【发布时间】:2014-07-13 23:17:45
【问题描述】:
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 函数编写的。

【问题讨论】:

  • 好吧,这些都是未初始化的:char linhaLida[BUFFER],linhaTemp[BUFFER],linhaEscrever[BUFFER]; 但是如果没有self-contained example 的代码给出这个错误,就很难给出准确的答案。
  • 我不喜欢你的格式,也不喜欢在打开文件时使用序列点 (,)。
  • 如果我添加 linhaLida[BUFFER] = 0;它仍然给我同样的错误,我什至为 temp 变量分配了空间,它仍然给我错误。此外 linhaLida 将在 fgets 函数到达 if 之前对其进行初始化,如果 fgets 返回 NULL 则 if 是不可达的,我认为这不会是一个问题;抱歉摆弄比特我现在就改变它
  • 我的意思是添加 linhaLida[BUFFER] = {0};我有大约 0.5GB 的测试用例,没有一个给我这个错误,只有 valgrind 似乎做到了。此外,如果 fgets 返回 NULL 则 if 代码无法访问,如果 fgets 不返回 NULL 则初始化 linhaLida 并且我认为不存在未初始化的问题?
  • @FiddlingBits 逗号分隔符不是序列点

标签: c


【解决方案1】:

问题出在这里:

char delimitadorInterno[] = {delimitador,'\n'};

// ...

char * token = strtok(string,delimitador);

strtok 的第二个参数应该指向一个 string,它是要查找的分隔符。但是,您传递了一个指向两个不构成字符串的字符的指针,从而导致当 strtok 读取超过 '\n' 时 valgrind 捕获的未定义行为。

要解决此问题,请更改为:

char delimitadorInterno[] = { delimitador,'\n', 0 };

或许

char delimitadorInterno[] = { delimitador, 0 };

我猜你打算只使用分隔符作为分隔符(而不是分隔符后跟换行符的顺序)。由于 fgets 的结果只能在末尾有一个换行符,因此带有 \n 的版本将永远不会匹配任何内容,除非该行以 delimiter 结尾,在这种情况下它将匹配一次。

【讨论】:

  • 我以前有过,然后删除了它-.-。无论如何,非常感谢您花在这方面的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多