简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM