Here's the skeleton of my code:
int main (int argc, char* argv []) {
int n, offset, offset1;
int error = 0;
char *buf = NULL;
size_t len = 0;
char load_var[] = "load";
while(getline(&buf, &len, stdin) > 0) {
char cmd[65] = "";
while ((n = sscanf(buf,"%64s%n",cmd, &offset)) > 0) {
if (!strcmp(cmd,load_var)) {
char str[65] = "";
char another_str[65] = "";
int var_num;
buf += offset;
if ((var_num = sscanf(buf,"%64s%n%64s%n",str,&offset, another_str, &offset1)) > 0) {
some_function(str);
}
buf += offset;
}
}
}
free(buf);
return error;
}
Valgrind returns the messaged:
==15414== 120 bytes in 1 blocks are definitely lost in loss record 1 of 1
==15414== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15414== by 0x4EA5F54: getdelim (iogetdelim.c:66)
==15414== by 0x401B3B: main (dev.c:177)
I don't know where I'm using getline() wrong so that the program has memory error.
This comment is the correct answer:
buf += offset
that will invoke undefined behavior on your subsequent getline invokes, and your final free. Frankly, I'm amazed this doesn't crash. – WhozCraig
Valgrind should also report "invalid realloc" or similar before it reports the leak.
Related
Program is leaking memory and not able to fix it... This Program is reading data from text files and after reading data, it perform certain operation on data during this it leaks memory. Device has very limited memory & flash drive due to this I cannot run memory leaks checking tools.
Please advise to fix the memory leak issue
Please find code snippet below
int LanguageRequiredData(void)
{
char *data=NULL;
int retValue = 0 ;
retValue = GetString_English(&data);
if(retValue>0 && strlen(data)>0)
{
// Do Some Operation
}
if (data!=NULL)
{
Mem_free(data);
data = NULL;
}
}
int GetString_English(char **data)
{
int retValue = 0 ;
retValue = File_LoadContent(LANGSENGFILE,&(*data));
return retValue;
}
int File_LoadContent (char *file, char **content)
{
long size = File_Size(file);
char buf[256]={};
memset(buf,0x00,sizeof(buf));
if (*content)
{
Mem_free(*content);
}
*content = (char*) Mem_alloc((size+1) * sizeof(char));
TFILE * fd; fd=File_Open(file,"r"); if (fd==NULL) return 0;
while (File_Gets(buf,sizeof(buf),fd)!=NULL)
{
strcat(*content,buf);
memset(buf,0x00,sizeof(buf));
}
File_Close(fd); return 1;
}
void * Mem_alloc(size_t size)
{
int i;
void * ptr = NULL;
for (i = 0; i < 2; i++)
{
ptr = malloc(size);
if (ptr)
{
break;
}
}
if (ptr)
{
memset(ptr, 0, size);
}
return ptr;
}
void Mem_free(void * ptr)
{
if (ptr != NULL)
{
free(ptr);
}
ptr = NULL;
}
This part seems suspect:
while (File_Gets(buf,sizeof(buf),fd)!=NULL)
{
strcat(*content,buf);
memset(buf,0x00,sizeof(buf));
}
Specifically the strcat(). Is File_Gets() null-terminating what it writes to buf[]? If not then the strcat() may be reading/copying beyond the bounds of buf[], since it requires null-termination to know when to stop.
EDIT: I should point out that this is one of the reasons to recommend strncat() over strcat(). Using the "n" variants of the string functions (i.e. strncat(), strncpy(), strncmp()) helps prevent buffer overruns and is generally a good practice.
I have a problem with this piece of code that I modified many times (but the error always appeared):
It seems it has an error in freeing the last index of "filter"
char** read_and_filter(int fd) {
char buf[MAXLENGTH];
char **bufs=NULL;
char ch;
int j = 0, len = 0, t = 0;
while (!t && read(fd,&ch,1) == 1) {
switch (ch) {
case '\n':
t = 1;
case ' ':
bufs = realloc(bufs, (j+1)*sizeof(char*));
bufs[j++] = strndup(buf,len);
memset(buf,0,len);
len = 0;
break;
default:
buf[len++] = ch;
}
}
bufs[j] = 0;
return bufs;
}
int main(int argc, char **argv) {
char **filter;
int i,fd = open("input.txt",O_RDONLY);
filter = read_and_filter(fd);
for(i = 0; filter[i]; i++) {
printf("%s\n",filter[i]);
free(filter[i]);
}
return 0;
}
Here is the output:
0x1521030
HOME
0x1521050
2
0x1521070
A
0x1521010
8
0x15210c0
D
*** Error in `./test': free(): invalid pointer: 0x00000000015210c0 ***
I also tried to debug it with valgrind (it says me that the allocator tries to free 9 byte while the sum of characters is 8, strange no?) and gdb but nothing worked.
The first line of input.txt is "HOME 2 A 8 D\n"
The first time these lines are executed
bufs = realloc(bufs, (j+1)*sizeof(char*));
bufs[j++] = strndup(buf,len);
you obtain memory for 1 pointer (j was 0). This leaves no space for the closing NULL you write at the end of the function with
bufs[j] = 0;
so you are writing beyond the allocated memory, thus have undefined behaviour. Similarly each time you extend the buffer length.
Your bufs[j] = 0; at the end of read_and_filter writes into non-allocated memory. You never realloc-ed your bufs for that extra 0.
Memory leak is occurring from two places - strdup and the realloc
One answer is to make an initial allocation of memory for the buffer in main, using malloc and then pass a pointer to the allocated memory to the function. The function can then realloc the buffer, and copy data into it.
On return from the function, main can access the data directly from the buffer as it has a valid pointer to it, and then can free that memory before closing.
According to valgrind, the following has no memory loss.
void read_and_filter(int fd, char **bufs) {
char buf[100];
char ch;
int j = 0, len = 0, t = 0;
while (!t && read(fd,&ch,1) == 1) {
switch (ch) {
case '\n':
t = 1;
case ' ':
*bufs = realloc(*bufs, (j + 2)*sizeof(char*));
strncpy(bufs[j++], buf, len);
memset(buf,0,len);
len = 0;
break;
default:
buf[len++] = ch;
}
}
bufs[j] = 0;
return;
}
int main(int argc, char **argv) {
char *bptr = malloc(1);
int fd = open("input.txt", O_RDONLY);
read_and_filter(fd, &bptr);
printf("%s\n", bptr);
free(bptr);
return 0;
However I cannot be sure that this fully replicates the OP's intended functionality, but the overall approach does deal with the memory issues.
I'm currently writing a method that reads from an allocated block of memory and prints out its contents from a certain offset and up to a specified size, both of which are passed as parameters. I'm using char pointers to accomplish this, but keep getting a malloc error around line
char *content = (char *)malloc(size+1);
Code for the method:
int file_read(char *name, int offset, int size)
{
//First find file and its inode, if existing
int nodeNum = search_cur_dir(name);
if(nodeNum < 0) {
printf("File read error: file does not exist\n");
return -1;
}
//Size check, to avoid overflows/overreads
if(offset > inode[nodeNum].size || size > inode[nodeNum].size || (offset+size) > inode[nodeNum].size) {
printf("File read error: offset and/or size is too large\n");
return -1;
}
int i, read_size, track_size = size, content_offset = 0;
int target_block = offset / BLOCK_SIZE; //Defined as constant 512
int target_index = offset % BLOCK_SIZE;
char *raw_content = (char *)malloc(inode[nodeNum].size+1);
printf("check1\n"); //Debug statment
for(i = target_block; i < (inode[nodeNum].blockCount-(size/BLOCK_SIZE)); i++) {
disk_read(inode[nodeNum].directBlock[i], raw_content+content_offset);
content_offset += BLOCK_SIZE;
}
printf("check2\n"); //Debug statment
char *content = (char *)malloc(size+1);
memcpy(content, raw_content+target_index, size);
printf("%s\n", content);
free(raw_content);
free(content);
return 0;
}
and code for disk_read:
char disk[MAX_BLOCK][BLOCK_SIZE]; //Defined as 4096 and 512, respectively
int disk_read(int block, char *buf)
{
if(block < 0 || block >= MAX_BLOCK) {
printf("disk_read error\n");
return -1;
}
memcpy(buf, disk[block], BLOCK_SIZE);
return 0;
}
structure for node
typedef struct {
TYPE type;
int owner;
int group;
struct timeval lastAccess;
struct timeval created;
int size;
int blockCount;
int directBlock[10];
int indirectBlock;
char padding[24];
} Inode; // 128 byte
The error I get when using this method is one of memory corruption
*** glibc detected *** ./fs_sim: malloc(): memory corruption (fast): 0x00000000009f1030 ***
Now the strange part is, firstly this only occurs after I have used the method a few times - for the first two or three attempts it will work and then the error occurs. For instance, here is an example test run:
% read new 0 5
z12qY
% read new 0 4
z12q
% read new 0 3
*** glibc detected *** ./fs_sim: malloc(): memory corruption (fast): 0x00000000009f1030 ***
Even stranger still, this error disappears completely when I comment out
free(raw_content);
free(content);
Even through this would tie up the memory. I've read through previous posts regarding malloc memory corruption and understand this usually results from overwriting memory bounds or under allocating space, but I can't see where I could be doing this. I've attempted other sizes for malloc as well and these produced the best results when I commented out the lines freeing both pointers. Does anyone see what I could be missing? And why does this occur so inconsistently?
Code allocates space for characters and a null character, but does not insure the array is terminated with a null character before printing as a string.
char *content = (char *)malloc(size+1);
memcpy(content, raw_content+target_index, size);
// add
content[size] = '\0';
printf("%s\n", content);
Likely other issues too.
[Edit]
OP code is prone to mis-coding and dependent on inode[] to have coherent values (.blockCount . size). Clarify and simplify by determining the loop count and allocating per that count.
int loop_count = (inode[nodeNum].blockCount-(size/BLOCK_SIZE)) - target_block;
char *raw_content = malloc(sizeof *raw_content * loop_count * BLOCK_SIZE);
assert(raw_count);
for (loop = 0; loop < loop_count; loop++) {
i = target_block + loop;
disk_read(inode[nodeNum].directBlock[i], raw_content + content_offset);
content_offset += BLOCK_SIZE;
}
Also recommend checking the success of disk_read()
I'm working on a project that makes use of a string buffer. I've been getting random errors with free() and malloc() - Like "invalid next size (fast)" and suspects if it is due to some memory heap corruption. I'm using gcc. I used valgrind on the binary file and this is the summary :
ERROR SUMMARY: 26887 errors from 39 contexts (suppressed: 0 from 0)
I think that's a bit too high. I'm attaching a pastebin of the valgrind memcheck output here
Most of the problems seem to be from a single function : strbuf_addc(). strbuf is a string buffer that can grow automatically. I'm pasting some strbuf functions here.
int strbuf_add(struct strbuf *string, const char *c)
{
if(string == NULL || c == NULL) return 0;
while(*c != '\0') {
if(!strbuf_addc(string, *c++))
return 0;
}
return 1;
}
int strbuf_addc(struct strbuf *string, char c)
{
size_t space_available;
assert(string != NULL);
space_available = string->allocated - string->length;
if(space_available <= 1) {
if(!grow_buffer(string)) {
return 0;
}
}
string->buffer[string->length++] = c;
string->buffer[string->length] = '\0';
return 1;
}
static int grow_buffer(struct strbuf *string)
{
char *tmp;
size_t toallocate;
assert(string != NULL);
toallocate = string->allocated + (string->allocated / 2);
tmp = (char*) realloc(string->buffer, toallocate);
if(tmp) {
string->buffer = tmp;
string->allocated = toallocate;
return 1;
}
return 0;
}
I'm not sure if strbuf_addc is the culprit or some other function that I wrote. Please take a look. I am basically passing string literals as the second argument to strbuf_add. I'm not sure if they will be null terminated, but I suppose string literals in c are null terminated. I've also tried reading strings from a file, still some errors.
toallocate = string->allocated + (string->allocated / 2);
there might be situations where toallocate won't be bigger than string->allocated. so, realloc won't reserve more space for your string and you won't be able to add a character. valgrind keeps saying that :
==4755== Invalid write of size 1
so you just don't have space to append a char.
I get an
malloc: *** error for object 0x1001012f8: incorrect checksum for freed object
- object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
error in the following function:
char* substr(const char* source, const char* start, const char* end) {
char *path_start, *path_end, *path;
int path_len, needle_len = strlen(start);
path_start = strcasestr(source, start);
if (path_start != NULL) {
path_start += needle_len;
path_end = strcasestr(path_start, end);
path_len = path_end - path_start;
path = malloc(path_len + 1);
strncpy(path, path_start, path_len);
path[path_len] = '\0';
} else {
path = NULL;
}
return path;
}
How can I make this work? When I rewrite the function to allocate the memory using path[path_len + 1] it works just fine.
Now, the part I don't understand is, that I never even call free in any point of my application, as every allocated memory is needed for the program until it exists (which, AFAIK will invalidate every allocated memory anyway?!)
So, how can a freed object be corrupt if I never free one?
The function is called in this one:
char *read_response(int sock) {
int bytes_read;
char *buf = (char*)malloc(BUF_SIZE);
char *cur_position = buf;
while ((bytes_read = read(sock, cur_position, BUF_SIZE)) > 0) {
cur_position += bytes_read;
buf = realloc(buf, sizeof(buf) + BUF_SIZE);
}
int status = atoi(substr(buf, "HTTP/1.0 ", " "));
There is the realloc, am I using that wrong? I want to read the complete server response, so I have to reallocate after every iteration, don't I?
In read_response, you are probably overwriting the end of the buffer pointed to by buf.
The problem is that buf is a pointer, so sizeof(buf) will return the size of a pointer (probably 4 or 8 depending on your CPU). You are using sizeof as if buf were an array, which is not really the same thing as a pointer in C although they seem interchangeable in some contexts.
Instead of using sizeof, you need to be keeping track of the last size that you allocated for buf, and add BUF_SIZE to that each time you enlarge the buffer.
You should also consider that the read operation may be returning considerably fewer characters than BUF_SIZE on each call, so doing a realloc on buf in each iteration may be overkill. That probably won't cause any problems for you in terms of correctness, though; it will just use more memory than it needs to.
I would do something more like the code below.
#define MIN_BUF_SPACE_THRESHOLD (BUF_SIZE / 2)
char *read_response(int sock) {
int bytes_read;
char *buf = (char*)malloc(BUF_SIZE);
int cur_position = 0;
int space_left = BUF_SIZE;
if (buf == NULL) {
exit(1); /* or try to cope with out-of-memory situation */
}
while ((bytes_read = read(sock, buf + cur_position, space_left)) > 0) {
cur_position += bytes_read;
space_left -= bytes_read;
if (space_left < MIN_BUF_SPACE_THRESHOLD) {
buf = realloc(buf, cur_position + space_left + BUF_SIZE);
if (buf == NULL) {
exit(1); /* or try to cope with out-of-memory situation */
}
space_left += BUF_SIZE;
}
}
This version has the advantage of not trying to allocate more space if the read call comes back with only a few bytes of data.
This line
buf = realloc(buf, sizeof(buf) + BUF_SIZE);
is wrong. All reallocations are with the same size, BUF_SIZE + sizeof(char*). Then you are writing to unallocated memory when reading from the socket, overwriting memory previously freed by a realloc.
You have to keep track of the allocated size,
size_t current_buf_size = BUF_SIZE;
/* ... */
char *temp = realloc(buf, current_buf_size + BUF_SIZE);
if (temp == NULL) {
/* die or repair */
}
buf = temp;