malloc error during Build inode method for Unixlike file system - c

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).

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 */
}
}

Inconsistent malloc memory corruption

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()

C - Unable to free allocated memory

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.

C malloc increase buffer size

this is part of my code which reads an http response. It's supposed to increase the buffer size if it runs out of room. But i keep getting access violations. It happens when copying the data to the new buffer: memcpy(tmp_alloc, rec, ResponseLength); Any help/suggestions are appreciated.
#define SERVER_CHUNK 1024
char *rec = new char[10000];
char in_buff[SERVER_CHUNK];
int in_sz,
ResponseLength = 0,
rec_len = 10000;
in_sz = recv(ss,in_buff,SERVER_CHUNK,0);//get the response
while(in_sz > 0)
{
memcpy(rec + ResponseLength,in_buff,in_sz);
ResponseLength += in_sz;
if((ResponseLength + SERVER_CHUNK) > rec_len)
{
char *tmp_alloc = (char*) malloc (ResponseLength + SERVER_CHUNK);
if(!tmp_alloc)
{
printf("failed to alocate memory!\n");
break;
}
memcpy(tmp_alloc, rec, ResponseLength);
free(rec);
rec = tmp_alloc;
rec_len = ResponseLength + SERVER_CHUNK;
}
in_sz = recv(ss,in_buff,SERVER_CHUNK,0);
}
It's possible that you're corrupting the heap by mixing new[] with free(), which is not supported.
Change:
char *rec = new char[10000];
To:
char *rec = (char*) malloc( 10000);
and see if it makes any difference.
wouldn't it be better, to have this data as a list of buffers?
this way, you dont have to reallocate/copy all data every time you exceed your buffer.
you would only need to maintain a single/double linked list

Problems with 'Heap Buffer' Error in C

I get the following error in my C program:
Writing to heap after end of help buffer
Can you tell me what I'm missing?
char * path_delimiter(char * path)
{
int i = 0, index = 0, size = 0, length = (int)strlen(path);
char *tmp, *ans;
for(; i < length; i++) {
if(path[i] == PATH_DELIM[0]) {
break;
}
}
i++;
size = (int)strlen(path) - i;
ans = (char*)malloc(sizeof(path));
tmp = (char*)malloc(size);
strcpy(ans,path);
ans[i-1] = END_ARRAY;
if(size > 0)
{
strcpy(tmp,&path[i]);
realloc(path,size);
strcpy(path,tmp);
}
else
{
strcpy(path,ans);
}
free(tmp);
return ans;
}
This ...
sizeof(path)
... is the same as ...
sizeof(char *)
... which is the size of the pointer (not the size of the buffer which it's pointing to), so it's probably about 4.
So this ...
ans= (char*)malloc(sizeof(path));
... is a 4-byte buffer, and so this ...
strcpy(ans,path);
... is overwriting (writing past the end of) that buffer.
Instead of ...
malloc(sizeof(path));
... I think you want ...
malloc(strlen(path)+1);
You are not checking if malloc and realloc succeeded. More importantly, realloc may return a different handle which you are discarding.
Further, you have:
ans = malloc(sizeof(path));
...
strcpy(ans, path);
On the most common platform today, sizeof(path) is most likely 4 or maybe 8, regardless of the length of the character array path points to.
You normally need size = strlen(xxx) + 1; to allow for the null terminator on the string.
In this case, I think you need:
size = strlen(path) - i + 1;

Resources