Valgrind 对写入的未初始化值大喊大叫
该函数用从文件读取的数据填充动态生成的数组。 Valgrind 喊道:
==21124== Syscall param write(buf) points to uninitialised byte(s)
==21124== at 0x410D013: write (in /lib/libc-2.13.so)
==21124== by 0x8049839: main (mmboxd.c:437)
==21124== Address 0x41b49e6 is 6 bytes inside a block of size 344 alloc'd
==21124== at 0x4026D0E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==21124== by 0x8049924: messagesList (mmboxd.c:468)
==21124== by 0x80497F1: main (mmboxd.c:432)
==21124==
我猜 write 函数是由 realloc 调用的,但是 realloc 正在写入的结构体已填充在每个字段中。怎么了?
这里是函数、scruct 和调用它的主段:
typedef struct
{
char sender[41], recipient[41]; /* mittente e destinatario */
char obj[41], date[41]; /* oggetto e data del messaggio */
char flags; /* letto o no,marcato o no per la cancellazione */
size_t size; /* dimensione in bytes del corpo del messaggio */
} mmbox_mail_complete;
mmbox_mail_complete *messagesList(char *username, int *nmails)
{
/* NB - MAILBOX è così composta: 6 righe per ogni messaggio --> 1 mittente, 2 oggetto, 3 data, 4 flags, 5 size, 6 messaggio */
mmbox_mail_complete *mails = NULL; /* array di mail */
int n = 0; /* dimensione dell'array di mail */
int input; /* carattere letto */
char line[40]; /* linea letta */
int k; /* contatore */
FILE *file; /* puntatore al file da leggere/scrivere */
/* apro il file dell'utente */
if(!(file = fopen(userPath(username), "r"))) logMmboxd("failed opening user mailbox\n", 1);
else logMmboxd("succeded in opening user mailbox\n", 0);
/* leggo una riga alla volta appunto a partire dalla seconda e la stipo */
while((input = fgetc(file)) != EOF)
{
/* riavvolgo di un carattere avanzato nel caso non fosse EOF nella condizione del ciclo */
if(fseek(file, -1, SEEK_CUR) == -1) logMmboxd("failed seeking mailbox\n", 1);
else logMmboxd("seeked mailbox\n", 0);
/* alloco una nuova mail */
mails = realloc(mails, sizeof(mmbox_mail_complete) * (n+1));
n++;
/* leggo il mittente */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) mails[n-1].sender[k] = input;
mails[n-1].sender[k] = '\0';
/* leggo il mittente (in realtà ce l'ho gia in username) */
for(k=0; username[k] != '\0'; k++) mails[n-1].recipient[k] = username[k];
mails[n-1].recipient[k] = '\0';
/* leggo l'oggetto */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) mails[n-1].obj[k] = input;
mails[n-1].obj[k] = '\0';
/* leggo la data */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) mails[n-1].date[k] = input;
mails[n-1].date[k] = '\0';
/* leggo il flag */
input = fgetc(file);
mails[n-1].flags = input;
input = fgetc(file);
/* leggo la dimensione del messaggio */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) line[k] = input;
line[k] = '\0';
mails[n-1].size = atoi(line);
/* mando avanti il puntatore nel file della lunghezza del messaggio */
if(fseek(file, mails[n-1].size+1, SEEK_CUR) == -1) logMmboxd("failed seeking (size) mailbox\n", 1);
else logMmboxd("seeked mailbox\n", 0);
}
*nmails = n;
fclose(file);
return mails;
}
/* in the main: the response struct is already memset to 0 */
response.result = SUCCESS;
mails = messagesList(users[k].username, &response.num);
response.num2 = 0;
response.size = sizeof(mmbox_mail_complete) * response.num;
answer(&response, mails); /* 437 line */
this function fills an array dinamically generated with data read from a file. Valgrind yells this:
==21124== Syscall param write(buf) points to uninitialised byte(s)
==21124== at 0x410D013: write (in /lib/libc-2.13.so)
==21124== by 0x8049839: main (mmboxd.c:437)
==21124== Address 0x41b49e6 is 6 bytes inside a block of size 344 alloc'd
==21124== at 0x4026D0E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==21124== by 0x8049924: messagesList (mmboxd.c:468)
==21124== by 0x80497F1: main (mmboxd.c:432)
==21124==
The write function is called by realloc I guess,but the struct realloc is writing is filled in every field. What's wrong?
Here the function, the scruct and the main segment where it is called:
typedef struct
{
char sender[41], recipient[41]; /* mittente e destinatario */
char obj[41], date[41]; /* oggetto e data del messaggio */
char flags; /* letto o no,marcato o no per la cancellazione */
size_t size; /* dimensione in bytes del corpo del messaggio */
} mmbox_mail_complete;
mmbox_mail_complete *messagesList(char *username, int *nmails)
{
/* NB - MAILBOX è così composta: 6 righe per ogni messaggio --> 1 mittente, 2 oggetto, 3 data, 4 flags, 5 size, 6 messaggio */
mmbox_mail_complete *mails = NULL; /* array di mail */
int n = 0; /* dimensione dell'array di mail */
int input; /* carattere letto */
char line[40]; /* linea letta */
int k; /* contatore */
FILE *file; /* puntatore al file da leggere/scrivere */
/* apro il file dell'utente */
if(!(file = fopen(userPath(username), "r"))) logMmboxd("failed opening user mailbox\n", 1);
else logMmboxd("succeded in opening user mailbox\n", 0);
/* leggo una riga alla volta appunto a partire dalla seconda e la stipo */
while((input = fgetc(file)) != EOF)
{
/* riavvolgo di un carattere avanzato nel caso non fosse EOF nella condizione del ciclo */
if(fseek(file, -1, SEEK_CUR) == -1) logMmboxd("failed seeking mailbox\n", 1);
else logMmboxd("seeked mailbox\n", 0);
/* alloco una nuova mail */
mails = realloc(mails, sizeof(mmbox_mail_complete) * (n+1));
n++;
/* leggo il mittente */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) mails[n-1].sender[k] = input;
mails[n-1].sender[k] = '\0';
/* leggo il mittente (in realtà ce l'ho gia in username) */
for(k=0; username[k] != '\0'; k++) mails[n-1].recipient[k] = username[k];
mails[n-1].recipient[k] = '\0';
/* leggo l'oggetto */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) mails[n-1].obj[k] = input;
mails[n-1].obj[k] = '\0';
/* leggo la data */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) mails[n-1].date[k] = input;
mails[n-1].date[k] = '\0';
/* leggo il flag */
input = fgetc(file);
mails[n-1].flags = input;
input = fgetc(file);
/* leggo la dimensione del messaggio */
for(k=0; (input=fgetc(file)) != '\n' && input != EOF; k++) line[k] = input;
line[k] = '\0';
mails[n-1].size = atoi(line);
/* mando avanti il puntatore nel file della lunghezza del messaggio */
if(fseek(file, mails[n-1].size+1, SEEK_CUR) == -1) logMmboxd("failed seeking (size) mailbox\n", 1);
else logMmboxd("seeked mailbox\n", 0);
}
*nmails = n;
fclose(file);
return mails;
}
/* in the main: the response struct is already memset to 0 */
response.result = SUCCESS;
mails = messagesList(users[k].username, &response.num);
response.num2 = 0;
response.size = sizeof(mmbox_mail_complete) * response.num;
answer(&response, mails); /* 437 line */
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不会写入发送者/接收者名称的整个字段,而只会写入第一个 NUL 字节。虽然如果 NUL 终止符后面的字节未初始化,您的程序可能会正确运行,但 valgrind 无法知道这是一个字符串并且这些字节是不相关的。
You are not writing the entire field for the sender/recipient names, but only until the first NUL byte. While your program is probably going to operate correctly if the bytes following the NUL terminator are not initialized, valgrind cannot know that this is a string and that these bytes are irrelevant.