I tested this program under Visual Studio 2010, 2008 and Codeblock 10.2 (gcc 4.x.x), it worked perfectly. However, when I connect to my school compiler, they use gcc 3.3.4, it crashed, and the result was Memory fault (coredump), and I have no idea why? I wonder is gcc 3.3.4 bug? Or something was wrong? Any idea?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int MEM_SIZE = 65536;
/* Cache definition */
struct _tag_cache {
int tag;
int *block;
};
typedef struct _tag_cache cache;
/* Function Prototype */
void set_params( int* , int* , int* );
void program();
void display_options();
int get_val_with_mess( const char* );
int *init_main_mem_of( int );
cache *init_cache_of( int );
void free_cache( cache** , int );
void write_cache( int* , cache* , int , int , int );
void read_cache( int* , cache* , int , int , int );
void show_content( int* , int );
/* Main Program */
int main() {
program();
printf( "\nGoodbye!\n" );
return 0;
}
/* Function Implementations */
void set_params( int *main_mem_size, int *cache_size, int *block_size ) {
*main_mem_size = get_val_with_mess( "Enter main memory size (words): " );
*cache_size = get_val_with_mess( "Enter cache size (words): " );
*block_size = get_val_with_mess( "Enter block size (words/block): " );
}
void program() {
int user_option = 0;
int main_mem_size = 65536;
int cache_size = 1024;
int block_size = 16;
int tags = main_mem_size / cache_size;
int *main_mem_ptr = NULL;
cache *cache_ptr = NULL;
// initialize memory
main_mem_ptr = init_main_mem_of( main_mem_size );
cache_ptr = init_cache_of( cache_size );
do {
// display menu
display_options();
// get user input
user_option = get_val_with_mess( "\nEnter selection: " );
switch( user_option ) {
case 1:
// if user set new parameters, free old memory
free_cache( &cache_ptr, tags );
free( main_mem_ptr );
// get new sizes
set_params( &main_mem_size, &cache_size, &block_size );
// calculate number of tags
tags = main_mem_size / cache_size;
// initialize new memory
main_mem_ptr = init_main_mem_of( main_mem_size );
cache_ptr = init_cache_of( cache_size );
break;
case 2:
read_cache( main_mem_ptr, cache_ptr, main_mem_size, block_size, cache_size );
break;
case 3:
write_cache( main_mem_ptr, cache_ptr, main_mem_size, block_size, cache_size );
break;
case 4:
break;
default:
printf( "Invalid options. Try again!\n" );
break;
}
}
while( user_option != 4 );
// free cache
if( cache_ptr != NULL ) {
free_cache( &cache_ptr, tags );
}
// free memory
if( main_mem_ptr != NULL ) {
//printf( "\nFreeing main memory.\n" );
free( main_mem_ptr );
}
}
void display_options() {
printf( "\nMain memory to cache memory mapping: \n" );
printf( "------------------------------------ \n" );
printf( "1) Set parameters \n" );
printf( "2) Read cache \n" );
printf( "3) Write to cache \n" );
printf( "4) Exit \n" );
}
int get_val_with_mess( const char *user_message ) {
int var;
printf( user_message );
scanf( "%d", &var );
return var;
}
int* init_main_mem_of( int size ) {
int i = 0;
int* p = ( int* )malloc( size * sizeof( int ) );
for( ; i < size; ++i )
*( p + i ) = size - i;
return p;
}
cache* init_cache_of( int tags ) {
int i = 0;
// one cache has 64 blocks
// one block has 16 words
cache* p = ( cache* )malloc( tags * sizeof( cache ) );
for( ; i < tags; ++i ) {
p[i].tag = -1;
p[i].block = NULL;
}
return p;
}
void free_cache( cache **p, int size ) {
int i = 0;
for( ; i < size; ++i ) {
// if that block is not NULL, free it
if( ( *p )[i].block != NULL ) {
//printf( "\nFreeing block of tag %d.", i );
free( ( *p )[i].block );
}
}
// free cache
//printf( "\nFreeing cache.\n" );
free( *p );
}
void write_cache( int* main_mem_ptr, cache* cache_ptr, int mm_size, int block_size, int cache_size ) {
int addr = 0;
int value = 0;
int tag;
int block;
int word;
int i;
int base_offset;
int already_missed = 0;
addr = get_val_with_mess( "Enter main memory address to write to: " );
value = get_val_with_mess( "Enter value to write: " );
base_offset = ( addr / block_size ) * block_size;
tag = addr / cache_size;
word = addr % block_size;
block = ( addr % cache_size ) / block_size;
// assign new value
main_mem_ptr[addr] = value;
// if tag doesn't match
if( cache_ptr[block].tag != tag ) {
printf( "Write miss!\n" );
already_missed = 1;
cache_ptr[block].tag = tag;
}
// if cache block memory is NULL
if( cache_ptr[block].block == NULL ) {
if( already_missed == 0 )
printf( "Write miss!\n" );
// allocate block
cache_ptr[block].block = ( int* )malloc( block_size * sizeof( int ) );
}
// transfer from main memory to cache
for( i = 0; i < block_size; ++i ) {
cache_ptr[block].block[i] = main_mem_ptr[base_offset + i];
}
printf( "Word %d of block %d with tag %d contains %d\n", word, block, tag, cache_ptr[block].block[word] );
}
void read_cache( int* main_mem_ptr, cache* cache_ptr, int mm_size, int block_size, int cache_size ) {
int addr = 0;
int value = 0;
int tag;
int block;
int word;
int i;
int base_offset;
int already_missed = 0;
addr = get_val_with_mess( "Enter main memory address to read from: " );
base_offset = ( addr / block_size ) * block_size;
tag = addr / cache_size;
word = addr % block_size;
block = ( addr % cache_size ) / block_size;
// if tag doesn't match
if( cache_ptr[block].tag != tag ) {
printf( "Read miss!\n" );
already_missed = 1;
cache_ptr[block].tag = tag;
}
if( cache_ptr[block].block == NULL ) {
if( already_missed == 0 )
printf( "Read miss!\n" );
// allocate block
cache_ptr[block].block = ( int* )malloc( block_size * sizeof( int ) );
}
// read from main memory
for( i = 0; i < block_size; ++i ) {
cache_ptr[block].block[i] = main_mem_ptr[base_offset + i];
}
printf( "Word %d of block %d with tag %d contains %d\n", word, block, tag, cache_ptr[block].block[word] );
}
void show_content( int* p, int size ) {
int i = 0;
for( ; i < size; ++i )
printf( "%d, ", p[i] );
}
Input and output sample
Main memory to Cache memory mapping:
--------------------------------------
1) Set parameters
2) Read cache
3) Write to cache
4) Exit
Enter selection: 1
Enter main memory size (words): 65536
Enter cache size (words): 1024
Enter block size (words/block): 16
Main memory to Cache memory mapping:
--------------------------------------
1) Set parameters
2) Read cache
3) Write to cache
4) Exit
Enter selection: 3
Enter main memory address to write to: 65535
Enter value to write: 14
Write miss!
Word 15 of block 63 with tag 63 contains value 14
Main memory to Cache memory mapping:
--------------------------------------
1) Set parameters
2) Read cache
3) Write to cache
4) Exit
Enter selection: 2
Enter main memory address to read from: 65535
Word 15 of block 63 with tag 63 contains value 14
Main memory to Cache memory mapping:
--------------------------------------
1) Set parameters
2) Read cache
3) Write to cache
4) Exit
Enter selection: 3
Enter main memory address to write to: 65534
Enter value to write: 512
Word 14 of block 63 with tag 63 contains value 512
Main memory to Cache memory mapping:
--------------------------------------
1) Set parameters
2) Read cache
3) Write to cache
4) Exit
Enter selection: 2
Enter main memory address to read from: 1023
Read miss!
Word 15 of block 63 with tag 0 contains value 64513
Main memory to Cache memory mapping:
--------------------------------------
1) Set parameters
2) Read cache
3) Write to cache
4) Exit
Enter selection: 4
%
I haven’t gone right through the program, but the first thing I spotted is that when you call
malloc()you don’t check for success.e.g.
The problem might be the school computer running out of memory, rather than the compiler. Go through the program and make sure that every call to
malloc()succeeds.