我发现某个地方存在内存泄漏/错误后,已经坐了几个小时来检查这段代码那个泄漏在哪里?如何解决?这是Dr.Memory报告:
Dr. Memory version 2.3.0
Running "C:\Users\Beni\source\repos\Magshimim_EX8\Debug\Magshimim_EX8.exe"
Using system call file C:\Users\Beni\AppData\Roaming\Dr. Memory\symcache\syscalls_wow64.txt
Error #1: UNADDRESSABLE ACCESS: reading 1 byte(s)
replace_strlen
d:\drmemory_package\drmemory\replace.c(412):
Magshimim_EX8.exe!?
??:0
Magshimim_EX8.exe!?
??:0
Magshimim_EX8.exe!?
??:0
Magshimim_EX8.exe!?
??:0
Magshimim_EX8.exe!?
??:0
KERNEL32.dll!BaseThreadInitThunk
??:0
ERRORS FOUND:
1 unique, 1 total unaddressable access(es)
0 unique, 0 total uninitialized access(es)
0 unique, 0 total invalid heap argument(s)
0 unique, 0 total GDI usage error(s)
0 unique, 0 total handle leak(s)
0 unique, 0 total warning(s)
0 unique, 0 total, 0 byte(s) of leak(s)
0 unique, 0 total, 0 byte(s) of possible leak(s)
Details: C:\Users\Beni\AppData\Roaming\Dr. Memory\DrMemory-Magshimim_EX8.exe.5208.000\results.txt
WARNING: application exited with abnormal code 0xc0000005
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#define FALSE 0
#define TRUE !FALSE
#define FIRST_TWO_FILES 2
#define FIRST_TWENTY_PRECENTS 1
#define MIDDLE_SIXTY_PRECENTS 2
#define LAST_TWENTY_PRECENTS 3
long findLenOfFile(FILE * file);
char* readFile(FILE* f, char* dest, long len);
char menu(char* scanFolder, char* virusSignature);
char** writeFilesFromFolder(char* scanFolder, char ** filesList, int* len);
char* writePart(char* src, char* dest, int length, int* newLen, int part);
int findSignature(char* virusSignature, char* buffer, int sigLen, int bufferLen);
void scanFiles(char* scanFolder, char** filesList, int amountOfFiles, char* virusSignature, long virusLength, char option);
int main(int argc, char* argv[])
{
char* log = malloc(sizeof(char)*strlen(argv[1]) + sizeof(char)*strlen("\\Log.txt") + 4);
FILE* virusSignatureFile = fopen(argv[2], "rb");
long virusLength = 0;
char** filesList = (char**)malloc(sizeof(char) * 0);
char* virusSignature = 0;
int amountOfFiles = 0;
char option = 0;
int i = 0;
virusLength = findLenOfFile(virusSignatureFile);
// get the virusSignature as a string and write the files to check into the filesList
virusSignature = readFile(virusSignatureFile, virusSignature, virusLength);
filesList = writeFilesFromFolder(argv[1], filesList, &amountOfFiles);
// create log file
strcpy(log, "");
strcat(log, argv[1]);
strcat(log, "\\Log.txt");
FILE * logFile = fopen(log, "w");
fprintf(logFile, "Anti-virus began! Welcome!\n\nFolder to scan:\n%s\nVirus signature:\n%s\n\nScanning option:\n", argv[1], argv[2]);
// get scanning option (normal or quick) and continue accordingly
option = menu(argv[1], argv[2]);
if (option == '0') {
fprintf(logFile, "Normal Scan\n\n");
}
else {
fprintf(logFile, "Quick Scan\n\n");
}
fprintf(logFile, "Results:\n");
fclose(logFile);
// initiate scan
scanFiles(argv[1], filesList, amountOfFiles, virusSignature, virusLength, option);
fclose(virusSignatureFile);
free(log);
free(filesList);
free(virusSignature);
getchar();
return 0;
}
/*
This function will print the scanning folder path and signature path, also will print the option menu to the user of quick or normal scan,
after that function will return user option(0, or other key)
input: scanFolder path (string), virus signature path (also string)
output: user option (char: '0', or other key)
*/
char menu(char * scanFolder, char * virusSignature)
{
char userOption = '\0';
printf("Welcome to my Virus Scan!\n\nFolder to scan: %s\nVirus signature: %s\n\nPress 0 for a norman scan or any other key for a quick scan: ", scanFolder, virusSignature);
userOption = getchar();
printf("Scanning began...\nThis process may take several minutes...\n\n");
return userOption;
}
/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char** writeFilesFromFolder(char * scanFolder, char ** filesList, int* len)
{
DIR *d = 0;
struct dirent *dir;
d = opendir(scanFolder);
int i = 0;
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if (i > 1)
{
filesList = (char**)realloc(filesList, sizeof(filesList) + sizeof(char*) + 4);
*(filesList + (i - FIRST_TWO_FILES)) = (char*)malloc(sizeof(char) * strlen(dir->d_name) + 1);
strcpy(*(filesList + (i - FIRST_TWO_FILES)), (dir->d_name));
}
i++;
}
closedir(d);
}
*len = i - FIRST_TWO_FILES; //first two names is "." and ".."
return filesList;
}
/*
This function will read the contents of a file into a string
input: a file (FILE *) to read from
output: char* with the contents of the file
*/
char* readFile(FILE* f, char * dest, long len)
{
dest = (char*)malloc(sizeof(char) * len);
fread(dest, 1, len, f);
return dest;
}
void scanFiles(char * scanFolder, char ** filesList, int amountOfFiles, char * virusSignature, long virusLength, char option)
{
char* log = malloc(sizeof(char)*strlen(scanFolder) + sizeof(char)*strlen("\\Log.txt") + 1);
char * buffer = (char*)malloc(sizeof(char) * 0);
char* subBuffer = 0;
char* slash = "\\";
long length = 0;
char* name = 0;
int subLen = 0;
int i = 0;
FILE * f;
// reopen log file and append to it
strcpy(log, "");
strcat(log, scanFolder);
strcat(log, "\\Log.txt");
FILE * logFile = fopen(log, "a");
// iterate over each file
for (i = 0; i < amountOfFiles; i++)
{
name = (char*)malloc(sizeof(char) * strlen(scanFolder) + 1 + sizeof(char) * strlen(slash) + sizeof(char) * strlen(*(filesList + i)) + 20);
// open current file
strcpy(name, "");
strcat(name, scanFolder);
strcat(name, slash);
strcat(name, *(filesList + i));
f = fopen(name, "rb");
length = findLenOfFile(f);
if (f != NULL) // if file can be accessed
{
buffer = readFile(f, buffer, length);
if (option == '0') { // Normal Mode
if (findSignature(virusSignature, buffer, virusLength, length))
{
printf("%s - Infected!\n", name);
fprintf(logFile, "%s - Infected!\n", name);
}
else
{
printf("%s - Clean\n", name);
fprintf(logFile, "%s - Clean\n", name);
}
}
else { // Quick Mode
subBuffer = writePart(buffer, subBuffer, length, &subLen, FIRST_TWENTY_PRECENTS); // get first 20%
if (findSignature(virusSignature, subBuffer, virusLength, subLen))
{
printf("%s - infected! (first 20%%)\n", name);
fprintf(logFile, "%s - infected! (first 20%%)\n", name);
}
else {
free(subBuffer);
subBuffer = writePart(buffer, subBuffer, length, &subLen, LAST_TWENTY_PRECENTS); // get last 20%
if (findSignature(virusSignature, subBuffer, virusLength, subLen))
{
printf("%s - Infected! (last 20%%)\n", name);
fprintf(logFile, "%s - Infected! (last 20%%)\n", name);
}
else {
subBuffer = writePart(buffer, subBuffer, length, &subLen, MIDDLE_SIXTY_PRECENTS); // get the 60% left in the middle
if (findSignature(virusSignature, subBuffer, virusLength, subLen))
{
printf("%s - Infected!\n", name);
fprintf(logFile, "%s - Infected!\n", name);
}
else {
printf("%s - clean\n", name);
fprintf(logFile, "%s - Clean\n", name);
}
}
}
free(subBuffer);
}
fclose(f);
}
else
{
printf("No file found\n");
}
free(*(filesList + i));
free(name);
}
fclose(logFile);
free(log);
free(buffer);
getchar();
}
/*
This function will write part of the file (beginning, middle or end) to a string
input: source (string) to take the information from, destination (string) to write a part of the source to it,
length (int) of the source string, a pointer (int*) to store the new length of the destination string and
part of the file to write from (int) 1,2 or 3: first 20%, 60% in the middle and last 20% accordingly
output: string containing the desired part of the source string
*/
char* writePart(char *src, char *dest, int length, int *newLen, int part) {
int i = 0;
int percentedLength = 0;
int count = 0;
percentedLength = (int)(length / 5); // this len is 20% of the entire file's length
if (part == FIRST_TWENTY_PRECENTS) // return beginning
{
dest = (char*)malloc(sizeof(char) * percentedLength);
*newLen = percentedLength;
for (i = 0; i < percentedLength; i++)
{
*(dest + i) = *(src + i);
}
}
else if (part == MIDDLE_SIXTY_PRECENTS) // return middle
{
// allocate space for the middle: The entire file size minus 20% from the start and 20% from the end
dest = (char*)malloc(sizeof(char) * (length - 2 * percentedLength));
*newLen = length - 2 * percentedLength;
for (i = percentedLength; i < length - percentedLength; i++) {
*(dest + count) = *(src + i);
count++;
}
}
else if (part == LAST_TWENTY_PRECENTS) // return end
{
dest = (char*)malloc(sizeof(char) * percentedLength);
*newLen = percentedLength;
for (i = length - percentedLength; i < length; i++)
{
*(dest + count) = *(src + i);
count++;
}
}
return dest;
}
/*
function that finds the length of a file
input: file (FILE *)
output: the file's length (long)
*/
long findLenOfFile(FILE * file)
{
long length = 0;
fseek(file, 0, SEEK_END);
length = ftell(file);
fseek(file, 0, SEEK_SET);
return length;
}
/*
function checks whether a file contains the virusSignature. It iterates over each letter of the file and checks
if it is the same as the first letter in the virusSignature. If it is, it checks the rest of the characters and
returns True if a match is found. if not it continues the same process until the end of the file is reached.
input: The virusSignature (string), a buffer with the content of a file (string), the signature's length (int)
and the buffer's length (int)
output: True if signature is in file, False otherwise
*/
int findSignature(char* virusSignature, char* buffer, int sigLen, int bufferLen)
{
int found = 0;
int i = 0;
int j = 0;
for (i = 0; i < bufferLen - (sigLen - 1); i++) {
if (*(buffer + i) == *virusSignature) // check if a letter is the same as first letter in virusSignature
{
found = TRUE;
// check if the rest of the letters match the signature and stop if one doesn't
for (j = 1; (j < sigLen) && found; j++) {
if (*(buffer + (i + j)) != *(virusSignature + j)) {
found = FALSE;
}
}
if (found) {
return TRUE; // if we got a match, return true!
}
}
}
return FALSE;
}
realloc
中的writeFilesFromFolder
调用有错误。
它是:
filesList = (char **) realloc(filesList, sizeof(filesList) + sizeof(char *) + 4);
注意,为filesList
分配的空间为恒定。当添加新元素时,它[
不是
检测到该工具的内存泄漏。内存泄漏意味着您无法free
超出范围的指针。相反,您存储的数据超出了分配的区域的末端,浪费了其中的任何内容,这可能是malloc
等的[隐藏]链指针区域。等用于跟踪分配。 我不确定sizeof
中的任何一个因素如何,但是filesList
是一个指针,所以sizeof(filesList)
是常数[在32位计算机上为4或在64位计算机上为8]。
分配的空间必须与i
成比例增加。
顺便说一句,不要投射malloc
:Do I cast the result of malloc?
/*
This function writes all files name from folder to the filesList
input: the scanning folder path
output: amount of files
*/
char **
writeFilesFromFolder(char *scanFolder, char **filesList, int *len)
{
DIR *d = 0;
struct dirent *dir;
d = opendir(scanFolder);
int i = -FIRST_TWO_FILES;
if (d) {
while ((dir = readdir(d)) != NULL) {
if (i >= 0) {
filesList = realloc(filesList,sizeof(*filesList) * (i + 1));
filesList[i] = strdup(dir->d_name);
}
i++;
}
closedir(d);
}
*len = i; // first two names is "." and ".."
return filesList;
}