C - Unable to free allocated memory - c

I have a problem with an application I'm currently developing. In this program I have to read huge amounts (billions) of data from text files and manage them consequently, but since it's a two students project, the reading part will be developed by my mate. For testing reason I wrote a small procedures that generates pseudo-random structures to replace what my mate will do.
The problem is the following: a big amount of the generated data (due to redundancy) can be discarded in order to free its memory. But even invoking the free() function the memory usage keeps growing. So I tried to develop a debug application that simply generates a chunk of data and immediately frees it. And repeats that for thousands of times. Well, I can't grasp the reason, but the memory allocated to the process grows to ~1.8 GB ram and then crashes. Why? The strangest thing, that makes me thing there's a lot I'm not understanding well, is that when the process crashes the malloc does NOT return a NULL pointer, because the process always crashes when readCycles == 6008 and bypasses the NULL check.
I already read other related topics here on StackOverflow and I understood why free() doesn't reduce the memory allocated to my process. That's fine. But why the memory usage keeps growing? Shouldn't the malloc allocate previously freed memory instead of constantly requesting new one?
This is the most relevant part of my code:
#define NREAD 1000
#define READCYCLES 10000
#define N_ALPHA_ILLUMINA 7
#define N_ALPHA_SOLID 5
#define SEQLEN 76
typedef struct{
char* leftDNA;
char* leftQuality;
unsigned long int leftRow;
char* rightDNA;
char* rightQuality;
unsigned long int rightRow;
} MatePair;
unsigned long int readCycles = 0;
MatePair* readStream(MatePair* inputStream, short* eof, unsigned long int* inputSize){
double r;
unsigned long int i, j;
unsigned long int leftRow;
int alphabet[] = {'A', 'C', 'G', 'T', 'N'};
inputStream = (MatePair*) malloc (sizeof(MatePair) * (NREAD + 1));
printf("%d\n", readCycles);
if (inputStream == NULL){
(*eof) = 1;
return;
}
for (i = 0; i < NREAD; i++){
leftRow = readCycles * NREAD + i;
inputStream[i].leftDNA = (char*) malloc (SEQLEN);
inputStream[i].rightDNA = (char*) malloc (SEQLEN);
inputStream[i].leftQuality = (char*) malloc (SEQLEN);
inputStream[i].rightQuality = (char*) malloc (SEQLEN);
for (j = 0; j < SEQLEN; j++){
r = rand() / (RAND_MAX + 1);
inputStream[i].leftDNA[j] = alphabet[(int)(r * 5)];
inputStream[i].rightDNA[j] = alphabet[(int)(r * 5)];
inputStream[i].leftQuality[j] = (char) 64 + (int)(r * 60);
inputStream[i].rightQuality[j] = (char) 64 + (int)(r * 60);
}
inputStream[i].leftDNA[SEQLEN - 1] = '\0';
inputStream[i].rightDNA[SEQLEN - 1] = '\0';
inputStream[i].leftQuality[SEQLEN - 1] = '\0';
inputStream[i].rightQuality[SEQLEN - 1] = '\0';
inputStream[i].leftRow = leftRow;
inputStream[i].rightRow = leftRow;
}
inputStream[i].leftRow = -1;
readCycles++;
(*inputSize) = NREAD;
(*eof) = readCycles > READCYCLES;
return inputStream;
}
int main(int argc, char* argv[]){
short eof = 0;
unsigned long int inputSize = 0;
MatePair* inputStream = NULL;
while (!eof){
inputStream = readStream(inputStream, &eof, &inputSize);
free(inputStream);
inputStream = NULL;
}
return 0;
}
I forgot to mention that, but before posting here, instead of calling free(inputStream), I tried invoking freeMemory(inputStream). Not sure if it's the correct way of doing it, though.
void freeMemory(MatePair* memblock){
for ( ; memblock->leftRow != 1; memblock++){
free(memblock -> leftDNA);
free(memblock -> leftQuality);
free(memblock -> rightDNA);
free(memblock -> rightQuality);
}
}

Memory leaks. How many 'malloc()' you have called, how many 'free()' you must use to free all allocated memory on the heap.
Thus,
inputStream[i].leftDNA = (char*) malloc (SEQLEN);
inputStream[i].rightDNA = (char*) malloc (SEQLEN);
inputStream[i].leftQuality = (char*) malloc (SEQLEN);
inputStream[i].rightQuality = (char*) malloc (SEQLEN);
these 'malloc()' functions must be paired with free().

You're not freeing all members allocated within the read loop, hence you're losing memory eahc time. Remember, you have to free everything you allocate with a malloc, not just your array.
Ok, Just look at your edit, and your freeMemory is still wrong. Try this;
void freeMemory(MatePair* inputStream)
{
for (i = 0; i < NREAD; i++){
free(inputStream[i].leftDNA);
free(inputStream[i].leftQuality);
free(inputStream[i].rightDNA);
free(inputStream[i].rightQuality);
}
free (inputStream);
}
Your free(memblock) was in the loop, which it shouldn't have been, and I'd tend to use the same iteration sequence on freeing as mallocing. You also need to error check after each malloc, and decide what to do with a NULL at that point.

Related

Removing print statement causes program to crash C

I have a c program where I copy one string to another but for some reason in my loop, if I remove a print statement I used for debugging once, the program crashes before I reach the print statement outside the while loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char * cats2 = malloc(sizeof(char));
cats2[0] = '\0';
char * cats = "this string is a cool cat";
getCopyFrom(cats, cats2);
free(cats2);
return 0;
}
void getCopyFrom(char* original, char* translation){
int index = 0;
char * current = malloc(sizeof(char));
current[0] = '\0';
while(index < (strlen(original))){
printf("%d\n", index);
current = realloc(current, sizeof(char) * 2);
current[index] = original[index];
current[index + 1] = '\0';
index++;
}
printf("%s\n", current);
free(current);
}
If I remove the printf("%d\n", index); from the while loop, the program will crash before the while loop ends. If I keep it, the program runs fine until the end where it returns a access violation error.
I'm not sure why either happens, am I missing something obvious or am I just not understanding malloc and realloc correctly?
edit:)
My previous question was answered, but I have a new problem. I added translation = realloc(translation, (strlen(current) + 1) * sizeof(char)); to the code to set the size of translation to the size of current but I get another access violation. Are you not able to realloc parameters or something?
current = realloc(current, sizeof(char) * 2);
but why is the second argument to realloc() in a loop a constant? It's like we want
current = realloc(current, sizeof(char) * (index + 1));
but once you do that you'll discover your code is really slow. The * 2 meant something. You really want to keep a separate array size and allocated size, and only call realloc when array size == allocated size and double allocated size.
if (index + 1 >= alloc) {
char *new = realloc(current, sizeof(char) * (alloc = (alloc == 0) ? 4 : (alloc << 1)));
if (!new) {
/* todo handle error */
}
}

malloc error during Build inode method for Unixlike file system

I am making unixlike file system as my university project and I am getting memory allocation error during making of file block with malloc method . Please help me. My code is as under :
char *BuildInode(int fileType)
{
int size = 0;
char *inode = (char *) malloc(sizeof(char) * SECTOR_SIZE_1/NUM_INODES_PER_BLOCK);
char *negativeOne = '\0';
inode[5] = fileType + 4;
int index;
for (index = 0; index < MAX_NUM_SECTORS_PER_FILE; index++)
{
inode[index + 2] = negativeOne;
}
return inode;
}
My guess is that SECTOR_SIZE_1 < NUM_INODES_PER_BLOCK and as a result (SECTOR_SIZE_1/NUM_INODES_PER_BLOCK is 0).
if SECTOR_SIZE_1 = 512 and NUM_INODE_BLOCKS = 250 then SECTOR_SIZE_1/NUM_INODES_PER_BLOCK is, guess what, 2,
Therefore the argument to malloc (sizeof(char) * SECTOR_SIZE_1/NUM_INODES_PER_BLOCK) is also 2, so you allocate a buffer of exactly 2 bytes.
Then in the for loop you fill this buffer to a size of MAX_NUM_SECTORS_PER_FILE + 2 = 32, or in other words you write 30 bytes beyond the end of the buffer.
A typical case of buffer overflow and subsequent undefined behaviour (an error message in your case).

Calloc/Malloc and freeing to often or too large a space?

Disclaimer, this is help with a school assignment. That being said, my issue only occurs about 50% of the time. Meaning if I compile and run my code without edits sometimes it will make it through to the end and other times it will not. Through the use of multiple print statements I know exactly where the issue is occurring when it does. The issue occurs in my second call to hugeDestroyer(right after the print 354913546879519843519843548943513179 portion) and more exactly at the free(p->digits) portion.
I have tried the advice found here (free a pointer to dynamic array in c) and setting the pointers to NULL after freeing them with no luck.
Through some digging and soul searching I have learned a little more about how free works from (How do malloc() and free() work?) and I wonder if my issue stems from what user Juergen mentions in his answer and that I am "overwriting" admin data in the free list.
To be clear, my question is two-fold.
Is free(p->digits) syntactically correct and if so why might I have trouble half the time when running the code?
Secondly, how can I guard against this kind of behavior in my functions?
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct HugeInteger
{
// a dynamically allocated array to hold the digits of a huge integer
int *digits;
// the number of digits in the huge integer (approx. equal to array length)
int length;
} HugeInteger;
// Functional Prototypes
int str2int(char str) //converts single digit numbers contained in strings to their int value
{
return str - 48;
}
HugeInteger *parseInt(unsigned int n)
{
int i = 0, j = 0;
int *a = (int *)calloc(10, sizeof(int));
HugeInteger *p = (HugeInteger *)calloc(1, sizeof(HugeInteger));
if(n == 0)
{
p->digits = (int *)calloc(1, sizeof(int));
p->length = 1;
return p;
}
while(n != 0)
{
a[i] = n % 10;
n = n / 10;
i++;
}
p->length = i;
p->digits = (int *)calloc(p->length, sizeof(int));
for(i = 0; i <= p->length; i++, j++)
p->digits[j] = a[i];
return p;
}
HugeInteger *parseString(char *str) //notice datatype is char (as in char array), so a simple for loop should convert to huge int array
{
int i = 0, j = 0;
HugeInteger *p = (HugeInteger *)calloc(1, sizeof(HugeInteger));
if(str == NULL)
{
free(p);
p = NULL;
return p;
}
else
{
for(i=0; str[i] != '\0'; i++)
;
p->length = i;
p->digits = (int *)calloc(p->length, sizeof(int));
for(; i >= 0; i--)
p->digits[j++] = str2int(str[i - 1]);
}
return p;
} //end of HugeInteger *parseString(char *str)
HugeInteger *hugeDestroyer(HugeInteger *p)
{
//printf("No problem as we enter the function\n");
if(p == NULL)
return p;
//printf("No problem after checking for p = NULL\n");
if(p->digits == NULL)
{
free(p);
p = NULL;
return p;
}
//printf("No Problem after checking if p->digits = NULL\n");
//else
//{
free(p->digits);
printf("We made it through free(p->digits)\n");
p->digits = NULL;
printf("We made it through p->digits = NULL\n");
free(p);
printf("We made it through free(p)\n");
p = NULL;
printf("We made it through p = NULL\n");
return p;
//}
//return NULL;
}//end of HugeInteger *hugeDestroyer(HugeInteger *p)
// print a HugeInteger (followed by a newline character)
void hugePrint(HugeInteger *p)
{
int i;
if (p == NULL || p->digits == NULL)
{
printf("(null pointer)\n");
return;
}
for (i = p->length - 1; i >= 0; i--)
printf("%d", p->digits[i]);
printf("\n");
}
int main(void)
{
HugeInteger *p;
hugePrint(p = parseString("12345"));
hugeDestroyer(p);
hugePrint(p = parseString("354913546879519843519843548943513179"));
hugeDestroyer(p);
hugePrint(p = parseString(NULL));
hugeDestroyer(p);
hugePrint(p = parseInt(246810));
hugeDestroyer(p);
hugePrint(p = parseInt(0));
hugeDestroyer(p);
hugePrint(p = parseInt(INT_MAX));
hugeDestroyer(p);
//hugePrint(p = parseInt(UINT_MAX));
//hugeDestroyer(p);
return 0;
}
First of all, really outstanding question. You did a lot of research on topic and generally speaking, solved this issue by yourself, I'm here mainly to confirm your findings.
Is free(p->digits) syntactically correct and if so why might I have trouble half the time when running the code?
Syntax is correct. #Shihab suggested in comments not to release p->digits and release p only, but such suggestion is wrong, it leads to memory leakages. There is a simple rule: for each calloc you must eventually call free, so your current approach in freeing p->digits and then p is totally fine.
However, program fails on a valid line. How is it possible? Quick answer: free can't do its work due to corruption of meta information responsible for tracking allocated/free blocks lists. At some point program corrupted meta information, but this was revealed only on attempt to use it.
As you already discovered, in most implementations memory routines such as calloc results into allocation of buffer with prepended meta-info. You receives pointer to buffer itself, but small piece of information right before this pointer is crucial for further buffer managing (e.g. freeing). Writing 11 integers into buffer intended for 10, you're likely to corrupt meta-info of block following the buffer. Whether corruption actually happens and what would be its consequences, is heavily dependent on both implementation specifics and current memory alignment (what block follows the buffer, what exactly meta-data is corrupted). It doesn't surprise me, that you see one crash per two executions, neither surprises me observing 100% crash reproduction on my system.
Secondly, how can I guard against this kind of behavior in my functions?
Let's start with fixing overflows. There are couple of them:
parseString: loop for(; i >= 0; i--) is executed length+1 times, so p->digits is overflown
parseInt: loop for (i = 0; i <= p->length; i++, j++) is executed length+1 times, so p->digits is overflown
Direct access to memory managing in C++ is error prone and troublesome to debug. Memory leakages and buffers overflows are the worst nightmare in programmers life, it's usually better to simplify/reduce direct usage of dynamic memory, unless you are studying to cope with it, of course. If you need to stick with a lot of direct memory managing, take a look at valgrind, it's intended to detect all such things.
By the way, there is also a memory leakage in your program: each call to parseInt allocates buffer for a, but never frees it.

Returning a char** gives me error "Address 0x0 is not stack'd, malloc'd or free'd

I need to return a list of strings. Those strings are read from the file (each string in each line of the file). The code below is not working:
void getStrings(char **container, FILE* file, int *numberOfLetters) {
char* line = NULL;
size_t l = 0;
ssize_t r;
container = (char**) malloc (sizeof(char*));
size_t lettersNumber= 1;
size_t numberOfStrings = 0;
size_t sizeOfContainer = 1;
while ((r = getline(&line, &l, file)) != -1) {
line[strlen(line) - 1] = '\0';
lettersNumber = lettersNumber + strlen(line);
if (numberOfStirngs == sizeOfContainer) {
sizeOfContainer= sizeOfContainer * 2;
char** temp = calloc(sizeOfContainer, sizeof(char**));
for (int k = 0; k < l; k++) {
temp[k] = container[k];
}
free(container);
container = temp;
}
container[numberOfStrings] = line;
numberOfStrings++;
}
if (line) {
free(line);
}
Because you calloc the whole array of pointers in each step, you loose all the strings from previous iterations and always only keep the last line. Since you use calloc, all these pointers are null, thus your error message.
The tool that is foreseen for such things is realloc and not malloc or calloc to keep the values that you already have stored.
There seem to be other things wrong, too. E.g you have only one line, all your lines are copied into that one, so previous lines are always overwritten. As BLUEPIXY correctly notes, you only change the value of your function parameter to the new values, you never return the new value to the caller.
Then, re-allocating memory in each iteration is a real waste. You should think of a strategy to do that more efficiently.

Strange behaviour on Realloc: invalid next size [duplicate]

This question already has an answer here:
free char*: invalid next size (fast) [duplicate]
(1 answer)
Closed 8 years ago.
I know there are tons of other realloc questions and answers and I have read almost all of them, but I still couldn't manage to fix my problem.
I decided to stop trying when I accidentaly discovered a very strange behaviour of my code.
I introduced a line to try something, but although I don't use the value of newElems in main, the line changes the behaviour.
When the line is commented, the code fails at first realloc. Including the line, the first realloc works. (it still crashes on the second one).
Any ideas on what might be happening?
int main(int argc, char** argv) {
Pqueue q = pqueue_new(3);
Node a = {.name = "a"}, b = {.name = "b"},
c = {.name = "c"}, d = {.name = "d"};
push(& q, & a, 3);
// the next one is the strange line: as you can see, it doesn't modify q
// but commenting it out produces different behaviour
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
push(& q, & b, 5);
push(& q, & c, 4);
char s[5];
Node* n;
for (int i = 1; i <= 65; ++i) {
sprintf(s, "%d", i);
n = malloc(sizeof *n);
n->name = strdup(s);
push(& q, n, i);
}
Node* current = NULL;
while ((current = pop(& q))) {
printf("%s ", current->name);
}
return 0;
}
and the push function:
void push(Pqueue* q, Node* item, int priority) {
if (q->size >= q->capacity) {
if (DEBUG)
fprintf(stderr, "Reallocating bigger queue from capacity %d\n",
q->capacity);
q->capacity *= 2;
Pqueue_elem* newElems = realloc(q->elems,
q->capacity * sizeof *newElems);
check(newElems, "a bigger elems array");
q->elems = newElems;
}
// append at the end, then find its correct place and move it there
int idx = ++q->size, p;
while ((p = PARENT(idx)) && priority > q->elems[p].priority) {
q->elems[idx] = q->elems[p];
idx = p;
}
// after exiting the while, idx is at the right place for the element
q->elems[idx].data = item;
q->elems[idx].priority = priority;
}
The pqueue_new function:
Pqueue pqueue_new(unsigned int size) {
if (size < 4)
size = 4;
Pqueue* q = malloc(sizeof *q);
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
return *q;
}
realloc will change the amount of memory that is allocated, if needed. It is also free to move the data to another place in memory if that's more efficient (avoiding memory fragmentation).
The function, then, returns a new pointer to the new location in memory where your data is hiding. You're calling realloc, and allocating (probably) four times as much memory as before, so it's very likely that that allocated memory is situated elsewhere in memory.
In your comment, you said realloc works like free + malloc. Well, in some cases it can behave similarly, however: realloc and free are different functions, that do different tasks. Both are functions that manage the dynamic memory, so yes, obviously there are similarities, and in the case of realloc, sometimes they can seem to be doing the same thing, however: As I explained here, realloc and free are fundamentally different functions
However, by not assigning the return value of realloc to q.elems, you're left with a pointer to a memory address that is no longer valid. The rest of your program can, and probably does, exhibit signs of undefined behaviour, then.
Unless you show some more code, I suspect this will take care of the problem:
//change:
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
//to
q.elems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
Or better yet, check for NULL pointers:
Pqueue_elem* newElems = realloc(q.elems, 4 * q.capacity * sizeof *newElems);
if (newElems == NULL)
exit( EXIT_FAILURE );// + fprintf(stderr, "Fatal error...");
q.elems = newElems;//<-- assign new pointer!
Looking at your pqueue_new function, I would suggest a different approach. Have it return the pointer to Pqueue. You're working with a piece of dynamic memory, treat it accordingly, and have your code reflect that all the way through:
Pqueue * pqueue_new(size_t size)
{//size_t makes more sense
if (size < 4)
size = 4;
Pqueue* q = malloc(sizeof *q);
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
return q;
}
Alternatively, pass the function a pointer to a stack variable:
void pqueue_new(Pqueue *q, size_t size)
{
if (q == NULL)
{
fprintf(stderr, "pqueue_new does not do NULL pointers, I'm not Chuck Norris");
return;//or exit
}
if (size < 4)
size = 4;
check(q, "a new queue.");
q->capacity = size;
q->elems = malloc(q->capacity * sizeof *(q->elems));
check(q->elems, "queue's elements");
}
//call like so:
int main ( void )
{
Pqueue q;
pqueue_new(&q, 3);
}
Those would be the more common approaches.
Thank you all for the suggestions! I wouldn't have solved it without them,
The strange behaviour was caused by an off by one error. I was reallocating the queue only when q->size >= q->capacity, but since q was indexed from 0, it meant that before realloc I was writing in a forbidden location (q->elems[q->size]), which messed everything up.

Resources