I've created a simple program that uses a thread to parse through a log file and print a value. After reading up on creating detached threads, I made the thread detached and destroyed the attribute (PTHREAD_CREATE_DETACHED) afterwards in my main function. I also exited the thread (not exiting created even more memory leaks). However, I still have memory leaks and an error, even though I'm pretty sure that I don't malloc anything in the rest of the program. Here is the full code:
*Credits go to Jonathan Leffler for the strtok_fixed function which parses a delimited string
static char *strtok_fixed(char *str, char const *delims)
{
static char *src = NULL;
char *p, *ret = 0;
if (str != NULL)
src = str;
if (src == NULL || *src == '\0') // Fix 1
return NULL;
ret = src; // Fix 2
if ((p = strpbrk(src, delims)) != NULL)
{
*p = 0;
//ret = src; // Unnecessary
src = ++p;
}
else
src += strlen(src);
return ret;
}
void * parse_log(void *arguments){
file = fopen("oms_requests.log", "r");
char c;
if (file == NULL){ //no valid file
printf("couldn't find the file\n");
} else {
int f = fseek(file, -2, SEEK_END);
if (f == 0){
int counter = 1;
c = fgetc(file);
while (c != '\n'){
counter++;
fseek(file, -counter, SEEK_END);
c = fgetc(file);
}
//now read last line in the log into buff
char buff[counter];
int l = fread(buff, 1, counter, file);
buff[counter-1] = '\0';
if (l != counter-1){
printf("counter is wrong\n");
} else {
//skip over 22 commas to get the value that I want
char *buffer = strtok_fixed(buff, ",");
for (int i = 0; i < 22; i++){
buffer = strtok_fixed(NULL, ",");
if (buffer == '\0') i++;
printf("%s\n", buffer);
}
printf("%ld\n", strtol(buffer, NULL, 10));
}
} else {
printf("error in getting to bottom of file\n");
}
}
fclose(file);
}
int main(int argc, char *argv[])
{
//create pthread attributes and set to detached
pthread_t thr;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
int l = pthread_create(&thr, &attr, parse_log, NULL);
if (l != 0){
printf("Didn't work\n");
return -1;
}
//destroy pthread attribute and exit
pthread_attr_destroy(&attr);
pthread_exit(&thr);
return 0;
}
Here is the report given by valgrind when I run the program:
==12387== HEAP SUMMARY:
==12387== in use at exit: 272 bytes in 1 blocks
==12387== total heap usage: 7 allocs, 6 frees, 2,510 bytes allocated
==12387==
==12387== Searching for pointers to 1 not-freed blocks
==12387== Checked 8,486,312 bytes
==12387==
==12387== 272 bytes in 1 blocks are possibly lost in loss record 1 of 1
==12387== at 0x4C2CC70: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12387== by 0x4012E54: _dl_allocate_tls (dl-tls.c:296)
==12387== by 0x4E3FDA0: pthread_create##GLIBC_2.2.5 (allocatestack.c:589)
==12387== by 0x400E11: main (in /afs/.ir.stanford.edu/users/d/i/dianale/CS107/assign1a/reassemble)
==12387==
==12387== LEAK SUMMARY:
==12387== definitely lost: 0 bytes in 0 blocks
==12387== indirectly lost: 0 bytes in 0 blocks
==12387== possibly lost: 272 bytes in 1 blocks
==12387== still reachable: 0 bytes in 0 blocks
==12387== suppressed: 0 bytes in 0 blocks
==12387==
==12387== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I've also tried pthread_detach(&thr) instead of setting an attribute (I've also tried having both at the same time), but I still get the exact same memory leaks and errors. Is there any way to fix this?
Pthreads allocates certain amount of memory for maintaining each thread's internal state. Detaching a thread only marks that those resources can be reclaimed immediately after the thread exits (as opposed to holding the state in case some other thread might need it). Butt these resources will remain allocated until the thread completes execution. Valgrind might report them as possible "leak".
Also remember that valgrind reports false positives at times. I don't see anything obvious in your code that could lead to leaks either. So I wouldn't worry about those "possible leaks" message.
Related
C Code:
This is the c code of the problem there is a card.raw file that contains the images.
// Include necesary libraries
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// Constants
typedef uint8_t BYTE;
int const BLOCK_SIZE = 512;
// Main function
int main(int argc, char *argv[])
{
// Check for usage
if (argc != 2)
{
printf("Usage: ./recover file.raw");
return 1;
}
// Open file
FILE *raw_file = fopen(argv[1], "r");
// If file could not be opened warn the user
if (raw_file == NULL)
{
printf("File could not be opened");
return 1;
}
// Generate jpg
// Create couter for name of jpg
unsigned int img_id = 0;
// Create block for storing the blocks of read data
BYTE block[BLOCK_SIZE];
// Create the file pointer for the generated jpgs
FILE *jpg_file = jpg_file = fopen("000.jpg", "w");
// Loop thru all blocks
while (fread(block, 1, BLOCK_SIZE, raw_file) == BLOCK_SIZE)
{
// Run if block start is jpg header
if (block[0] == 0xff && block[1] == 0xd8 && block[2] == 0xff && (block[3] & 0xf0) == 0xe0)
{
// Close only when a file has been opened
if (jpg_file != NULL)
{
fclose(jpg_file);
}
//Generate the filename to follow the pattern ###.jpg where ###
//is a 3 dijit number that is the id (the nth image) of the image
char filename[8];
sprintf(filename, "%03i.jpg", img_id);
// Create a jpg in base of the filename
jpg_file = fopen(filename, "w");
// Increase img id
img_id++;
// If file could not be created warn the user
if (raw_file == NULL)
{
printf("File could not be created");
return 1;
}
}
// If a file has already been opened write the data to it
if (jpg_file != NULL)
{
fwrite(block, 1, BLOCK_SIZE, jpg_file);
}
}
// Close file to prevent memory leaks
fclose(raw_file);
}
Valgrind Check:
==7293== Memcheck, a memory error detector
==7293== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7293== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==7293== Command: ./recover card.raw
==7293==
==7293==
==7293== HEAP SUMMARY:
==7293== in use at exit: 472 bytes in 1 blocks
==7293== total heap usage: 104 allocs, 103 frees, 237,536 bytes allocated
==7293==
==7293== 472 bytes in 1 blocks are still reachable in loss record 1 of 1
==7293== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==7293== by 0x4A086CD: __fopen_internal (iofopen.c:65)
==7293== by 0x4A086CD: fopen##GLIBC_2.2.5 (iofopen.c:86)
==7293== by 0x1092EB: main (recover.c:58)
==7293==
==7293== LEAK SUMMARY:
==7293== definitely lost: 0 bytes in 0 blocks
==7293== indirectly lost: 0 bytes in 0 blocks
==7293== possibly lost: 0 bytes in 0 blocks
==7293== still reachable: 472 bytes in 1 blocks
==7293== suppressed: 0 bytes in 0 blocks
==7293==
==7293== For lists of detected and suppressed errors, rerun with: -s
==7293== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Everything works except for that heap issue any help is appreciated!
This is some filler text because in the code there are the comments but it says 'It looks like your post is mostly code; please add some more details.' so yea.
I found the answer just put a fclose(jpg_file); at the end the file gets closed only at the start of the loop so when it ends it does not get closed.
// Include necessary libraries
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// Constants
typedef uint8_t BYTE;
int const BLOCK_SIZE = 512;
// Main function
int main(int argc, char *argv[])
{
// Check for usage
if (argc != 2)
{
printf("Usage: ./recover file.raw");
return 1;
}
// Open file
FILE *raw_file = fopen(argv[1], "r");
// If file could not be opened warn the user
if (raw_file == NULL)
{
printf("File could not be opened");
return 1;
}
// Generate jpg
// Create couter for name of jpg
unsigned int img_id = 0;
// Create block for storing the blocks of read data
BYTE block[BLOCK_SIZE];
// Create the file pointer for the generated jpgs
FILE *jpg_file = NULL;
// Loop thru all blocks
while (fread(block, 1, BLOCK_SIZE, raw_file) == BLOCK_SIZE)
{
// Run if block start is jpg header
if (block[0] == 0xff && block[1] == 0xd8 && block[2] == 0xff && (block[3] & 0xf0) == 0xe0)
{
// Close only when a file has been opened
if (jpg_file != NULL)
{
fclose(jpg_file);
}
//Generate the filename to follow the pattern ###.jpg where ###
//is a 3 dijit number that is the id (the nth image) of the image
char filename[8];
sprintf(filename, "%03i.jpg", img_id);
// Create a jpg in base of the filename
jpg_file = fopen(filename, "w");
// Increase img id
img_id++;
// If file could not be created warn the user
if (raw_file == NULL)
{
printf("File could not be created");
return 1;
}
}
// If a file has already been opened write the data to it
if (jpg_file != NULL)
{
fwrite(block, 1, BLOCK_SIZE, jpg_file);
}
}
// Close file to prevent memory leaks
fclose(raw_file);
fclose(jpg_file); // Here is the fix to the problem
}
I'm doing the CS50 practice: license. This code is to read license plate from a txt file and print them out.
Could someone please help me to know why my code still has a memory leak?
I still receive this message from Valgrind:
==11625== 448 bytes in 8 blocks are definitely lost in loss record 1 of 1
==11625== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==11625== by 0x109227: main (license.c:29)
==11625==
==11625== LEAK SUMMARY:
==11625== definitely lost: 448 bytes in 8 blocks
==11625== indirectly lost: 0 bytes in 0 blocks
==11625== possibly lost: 0 bytes in 0 blocks
==11625== still reachable: 0 bytes in 0 blocks
==11625== suppressed: 0 bytes in 0 blocks
==11625==
==11625== For lists of detected and suppressed errors, rerun with: -s
==11625== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
I thought I already freed all the memory previously claimed by malloc with this piece of code:
while (idx < 8)
{
free(plates[idx]);
idx ++;
}
Here is the full code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
// Check for command line args
if (argc != 2)
{
printf("Usage: ./read infile\n");
return 1;
}
// Create buffer to read into
char buffer[7];
// Create array to store plate numbers
char *plates[8];
FILE *infile = fopen(argv[1], "r");
int idx = 0;
while (fread(buffer, 1, 7, infile) == 7)
{
// Replace '\n' with '\0'
buffer[6] = '\0';
plates[idx] = malloc (7 * sizeof(char *));
// Save plate number in array
strcpy(plates[idx], buffer);
idx++;
}
for (int i = 0; i < 8; i++)
{
printf("%s\n", plates[i]);
}
//free memory
fclose(infile);
while (idx < 8)
{
free(plates[idx]);
idx ++;
}
return 0;
}
I'm kind of new to programming and I was writing a program to recover JPEG files present in "card.raw" by comparing the 4 continuous bytes. If they demarcated a JPEG the program had to copy a block of 512 bytes into a new file saved a xxx.jpg (000.jpg, 001.jpg, etc). If after the block had been copied, the start of a new JPEG was found, the current file would be closed and the next file would be opened to copy the next JPG. Else the next block would be copied in the same file.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int counter = 0;
if(argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
typedef uint8_t BYTE;
FILE *recover = fopen(argv[1], "r");
if(recover == NULL)
{
printf("ERRNO 1 IS %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fseek(recover, 0L, SEEK_END);
unsigned long size = ftell(recover);
fseek(recover, 0L, SEEK_SET);
BYTE *CHUNK = (BYTE*)malloc(size * sizeof(BYTE));
fread(CHUNK, sizeof(BYTE), size, recover); //Break recover into bytes
int j = 0;
char file[8] = "xxx.jpg";
FILE *f = NULL;
int s = 0;
while(j < size)
{
if(CHUNK[j] == 0xff && CHUNK[j + 1] == 0xd8 && CHUNK[j + 2] == 0xff) //Check if byte is JPEG format 1st byte
{
if(s == 0)
{
if(f != NULL)
{
f = NULL;
}
sprintf(file ,"%03d.jpg",counter); //Create custom file of format xxx.jpg
f = fopen(file,"w");
if(f == NULL)
{
printf("ERRNO 2 is %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fwrite(&CHUNK[j], 512, sizeof(BYTE), f); //Copy 512 bytes from start of JPEG file as 512 bytes form one 'block`
j += 512; //Increment to check initial bytes of next 'block'
s++;
}
else
{
fclose(f);
counter++;
s = 0;
}
}
else if(s > 0) //Else continue searching
{
fwrite(&CHUNK[j], 512, sizeof(BYTE), f);
j += 512;
}
else j += 512;
}
fclose(f);
fclose(recover);
free(&CHUNK);
return 0;
}
The program worked perfectly except for the fact the Valgrind gives me the following report:
==1560== Memcheck, a memory error detector
==1560== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1560== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1560== Command: ./recover card.raw
==1560==
==1560== Invalid free() / delete / delete[] / realloc()
==1560== at 0x4C32D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1560== by 0x400BF4: main (recover.c:69)
==1560== Address 0x1fff000510 is on thread 1's stack
==1560== in frame #1, created by main (recover.c:9)
==1560==
==1560==
==1560== HEAP SUMMARY:
==1560== in use at exit: 3,744,768 bytes in 1 blocks
==1560== total heap usage: 103 allocs, 103 frees, 3,981,816 bytes allocated
==1560==
==1560== 3,744,768 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1560== at 0x4C31B0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1560== by 0x4009FA: main (recover.c:26)
==1560==
==1560== LEAK SUMMARY:
==1560== definitely lost: 3,744,768 bytes in 1 blocks
==1560== indirectly lost: 0 bytes in 0 blocks
==1560== possibly lost: 0 bytes in 0 blocks
==1560== still reachable: 0 bytes in 0 blocks
==1560== suppressed: 0 bytes in 0 blocks
==1560==
==1560== For counts of detected and suppressed errors, rerun with: -v
==1560== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Valgrind seems to say that the problem is with the memory allocation in line 26:
BYTE *CHUNK = (BYTE*)malloc(size * sizeof(BYTE));
But I have freed the allocated memory with free(&CHUNK); at the end. I'd like to know why Valgrind reports that 3,744,768 bytes in 1 blocks have been definitely lost.
free(&CHUNK) is asking to free the space for the variable CHUNK, i.e. the (e.g. 4 or 8) bytes that the pointer itself take; besides not freeing the memory you are thinking of, this is undefined behavior, as you can free only memory that was allocated by malloc and friends, and I'm surprised you don't get a crash due to some sanity check inside the allocator.
What you actually need to do is to free the memory pointed-by CHUNK, so you have to do free(CHUNK).
Get a memory leak while using getline together with strsep. I know strsep modifies line - could this be the cause? That line is not freed correctly.
FILE *file = fopen("keywords.txt", "r");
if (file) {
char* line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, file)) != -1) { // Line 35
char *token;
while ((token = strsep(&line, "\t")) != NULL) {
// Do stuff
}
}
free(line);
fclose(file);
}
Valgrind returns this:
==6094== 4,680 bytes in 39 blocks are definitely lost in loss record 7 of 7
==6094== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6094== by 0x51AEBB4: getdelim (iogetdelim.c:66)
==6094== by 0x4009B3: read_keywords (main.c:35)
==6094== by 0x400959: renew_init (main.c:64)
==6094== by 0x400A48: main (main.c:68)
If I comment out strsep, there's no memory leak.
Tips?
When you pass &line to strsep, it will change the value of line. At the end of the inner loop, line will be NULL and free(line) will do nothing. This will also cause getline to allocate a new buffer instead of reusing the current one.
You should copy line to a new variable, e.g. char *line2 = line; and pass &line2 to strsep.
I am doing some learning with C, and am having trouble identifying a memory leak situation.
First, some code:
My main function:
#define FILE_NAME "../data/input.txt"
char * testGetLine( FILE * );
int testGetCount(void);
int main(void)
{
int count = 0;
FILE * fptr;
if ((fptr = fopen(FILE_NAME, "r")) != NULL) {
char * line;
while ((line = testGetLine(fptr)) != NULL) {
printf("%s", line);
free(line); count++;
}
free(line); count++;
} else {
printf("%s\n", "Could not read file...");
}
// testing statements
printf("testGetLine was called %d times\n", testGetCount());
printf("free(line) was called %d times\n", count);
fclose(fptr);
return 0;
}
and my getline function:
#define LINE_BUFFER 500
int count = 0;
char * testGetLine(FILE * fptr)
{
extern int count;
char * line;
line = malloc(sizeof(char) * LINE_BUFFER);
count++;
return fgets(line, LINE_BUFFER, fptr);
}
int testGetCount(void) {
extern int count;
return count;
}
my understanding is that I would need to call free everytime I have called my testGetLine function, which I do. By my count, on a simple text file with four lines I need to call free 5 times. I verify that with my testing statements in the following output:
This is in line 01
Now I am in line 02
line 03 here
and we finish with line 04
testGetLine was called 5 times
free(line) was called 5 times
What I am having trouble with is, valgrind says that I alloc 6 times, and am only calling free 5 times. Here is truncated output from valgrind:
HEAP SUMMARY:
in use at exit: 500 bytes in 1 blocks
total heap usage: 6 allocs, 5 frees, 3,068 bytes allocated
500 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
by 0x4007A5: testGetLine (testGetLine.c:13)
by 0x400728: main (tester.c:16)
LEAK SUMMARY:
definitely lost: 500 bytes in 1 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 0 bytes in 0 blocks
still reachable: 0 bytes in 0 blocks
suppressed: 0 bytes in 0 blocks
I feel I am missing something with the memory management. Where is the 6th memory allocation that valgrind says I am using? and how should I free it?
Followup to implement Adrian's answer
testGetLine adjustment:
char * testGetLine(FILE * fptr)
{
extern int count;
char * line;
line = malloc(sizeof(char) * LINE_BUFFER);
count++;
if (fgets(line, LINE_BUFFER, fptr) == NULL) {
line[0] = '\0';
}
return line;
}
main while loop adjustment:
while ((line = testGetLine(fptr))[0] != '\0') {
printf("%s", line);
free(line); count++;
}
free(line); count++;
fgets return description:
On success, the function returns str. If the end-of-file is
encountered while attempting to read a character, the eof indicator is
set (feof). If this happens before any characters could be read, the
pointer returned is a null pointer (and the contents of str remain
unchanged). If a read error occurs, the error indicator (ferror) is
set and a null pointer is also returned (but the contents pointed by
str may have changed).
When fgets doesn't read anything it doesn't return the char * that you used malloc on.
Therefore, the malloc in your last call isn't being freed. The statement after your while doesn't work as you want.
Solution: change your return and return line instead:
char * testGetLine(FILE * fptr)
{
extern int count;
char * line;
line = malloc(sizeof(char) * LINE_BUFFER);
count++;
fgets(line, LINE_BUFFER, fptr);
return line;
}