我有一个奇怪的错误,由valgrind在一个(愚蠢的)验证模块上发现一些堆分配。分析valgrind输出:“无效的免费()”
==8009== Invalid free()/delete/delete[]/realloc()
==8009== at 0x4C2A739: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8009== by 0x40263F: authenticate (server_utils.c:109)
==8009== by 0x401A27: main (server.c:240)
==8009== Address 0x51f1310 is 0 bytes inside a block of size 18 free'd
==8009== at 0x4C2A739: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8009== by 0x402633: authenticate (server_utils.c:108)
==8009== by 0x401A27: main (server.c:240)
=8009==
==8009== Invalid free()/delete/delete[]/realloc()
==8009== at 0x4C2A739: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8009== by 0x40264B: authenticate (server_utils.c:110)
==8009== by 0x401A27: main (server.c:240)
==8009== Address 0x51f1319 is 9 bytes inside a block of size 18 free'd
==8009== at 0x4C2A739: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8009== by 0x402633: authenticate (server_utils.c:108)
==8009== by 0x401A27: main (server.c:240)
==8009==
==8009== Invalid free()/delete/delete[]/realloc()
==8009== at 0x4C2A739: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8009== by 0x402657: authenticate (server_utils.c:111)
==8009== by 0x401A27: main (server.c:240)
==8009== Address 0x51f131e is 14 bytes inside a block of size 18 free'd
==8009== at 0x4C2A739: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8009== by 0x402633: authenticate (server_utils.c:108)
==8009== by 0x401A27: main (server.c:240)
==8009== ...
从我所了解的他说我做了三个无效的免费()线109-110-111。错误应该是我试图释放比实际分配的空间更多的空间,但我无法决定释放多少空间。另外我不明白为什么它会引用第108行(这也是一个免费的())。
这是从文档(无效免费):
MEMCHECK跟踪你的程序使用malloc /新分配的块,所以它可以准确地知道与否的说法释放/删除是合法与否。在这里,这个测试程序已经释放了同一块两次。与非法读/写错误一样,Memcheck试图理解释放的地址。如果这里的地址是先前已被释放的地址,那么您将被告知 - 使同一块的重复释放容易被发现。
如果您尝试释放一个指向堆块起点的指针,您也会收到此消息。
我真的无法想象如何在这些案件之一。
/* Authentication through <user_id:password:flag>
* Returns 1 on success, -1 if user_id doesn't exist, -2 on password mismatch
* On success sets access_permissions
*/
int authenticate(USR_PSW *received, int *access_permissions) {
/*Users file opening*/
FILE *fd;
fd = fopen(USERS_FILE, "r");
if (fd == NULL) {
fprintf(stderr, "Users file opening error\n");
exit(EXIT_FAILURE);
}
char *usr_psw_line = malloc(USR_SIZE + PSW_SIZE + 3 + 1);
if (usr_psw_line == NULL) {
fprintf(stderr, "Dynamic alloc error\n");
exit(EXIT_FAILURE);
}
char *usr_tok = malloc(USR_SIZE);
if (usr_tok == NULL) {
free(usr_psw_line);
fprintf(stderr, "Dynamic alloc error\n");
exit(EXIT_FAILURE);
}
char *psw_tok = malloc(PSW_SIZE);
if (psw_tok == NULL) {
free(usr_psw_line);
free(usr_tok);
fprintf(stderr, "Dynamic alloc error\n");
exit(EXIT_FAILURE);
}
char *flg_tok = malloc(sizeof (char) *2);
if (flg_tok == NULL) {
free(usr_psw_line);
free(usr_tok);
free(psw_tok);
fprintf(stderr, "Dynamic alloc error\n");
exit(EXIT_FAILURE);
}
/*Reading from file <user_id:password:flag> */
while (fgets(usr_psw_line, USR_SIZE - 1 + PSW_SIZE - 1 + 3 + 1, fd) != NULL) {
usr_tok = strtok(usr_psw_line, ":");
if (strcmp(usr_tok, received->user_id) == 0) {
/*user_id found, password check*/
psw_tok = strtok(NULL, ":");
/*password match*/
if (strcmp(psw_tok, received->password) == 0) {
flg_tok = strtok(NULL, ":");
*access_permissions = atoi(flg_tok);
free(usr_psw_line); //108
free(usr_tok);//109
free(psw_tok);//110
free(flg_tok);//111
fclose(fd);
return AUTHENTICATED;
} else { //password unmatch
free(usr_psw_line);
free(usr_tok);
free(psw_tok);
free(flg_tok);
fclose(fd);
return INVALID_PSW;
}
} else {
fseek(fd, 1, SEEK_CUR);
continue;
}
}
/*EOF Reached without match*/
free(usr_psw_line);
free(usr_tok);
free(psw_tok);
free(flg_tok);
fclose(fd);
return INVALID_USR;
}
头文件:
#ifndef __SERVER_UTILS_H__
#define __SERVER_UTILS_H__
#define USR_SIZE 9
#define PSW_SIZE 5
/*Authentication data structure definition*/
typedef struct{
char user_id[USR_SIZE]; // eg: user_123
char password[PSW_SIZE]; // eg: a1b2
} USR_PSW;
#define NM_MAX_SIZE 17
#define NR_MAX_SIZE 11
/*System record structure*/
typedef struct{
char first_name[NM_MAX_SIZE];
char last_name[NM_MAX_SIZE];
char number[NR_MAX_SIZE];
}TBOOK_RECORD;
/*Session status flags*/
#define NOT_AUTHENTICATED 0
#define AUTHENTICATED 1
#define INVALID_USR 2
#define INVALID_PSW 3
/*Persmissions flags*/
#define NO_PERM 0
#define READ_WRITE 1
#define O_WRITE 2
#define O_READ 3
/*Contains <user_id:password,flag> triplets stored in server */
#define USERS_FILE "users.txt"
/*Contains all telbook records <first_name:last_name:phone_number>*/
#define RECORDS_FILE "records.txt"
/*Single records file line max length (before \n) */
#define RECFILE_LINE_MAX_LEN 2*NM_MAX_SIZE+NR_MAX_SIZE+3+1;
/*Client operation*/
#define NO_OP 0
#define SEARCH_BY_NAME 1
#define SEARCH_BY_NUMBER 2
#define INSERT_RECORD 3
/*
* Returns number of bytes copied into buffer (excluding terminating null byte),
* or 0 on EOF, or -1 on error.
* size_t : used for sizes of objects.
* ssize_t: used for a count of bytes or an error indication (-1).
*/
ssize_t readline(int fd, void *buffer, size_t n);
/* Authentication through <user_id:password:flag>
* Returns 1 on success, -1 if user_id doesn't exist, -2 on password mismatch
* On success sets access_permissions
*/
int authenticate(USR_PSW *received, int *access_permissions);
int close_session(int sock_ds);
int search_by__(int op_code, TBOOK_RECORD *rc_rcvd, TBOOK_RECORD *rc_rspn
, FILE *fd, char *file_line);
int insert_record(TBOOK_RECORD *rc_rcvd);
#endif /* __SERVER_UTILS_H__ */
行号编 – 2013-03-25 18:43:43