开发者

Question regarding memory core dump in gcc 3.3.4

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.

int* init_main_mem_of(int size) 
{
    int i = 0;
    int* p = (int *)malloc(size * sizeof(int));
    if (!p)
    {
        puts("Error: Out of memory\n");
        exit(1);
    }
    for( ; i < size; ++i)
        p[i] = size - i;
    return p;
}

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.


aschelper caught the error from the screenshot. You specify a memory size of 65535 then tell it to write at address 65535 (one past the end of the array!).

When run in valgrind, the following output occurs (compiled with gcc-4.5.2):

$ valgrind ./test
==29640== Memcheck, a memory error detector
==29640== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==29640== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==29640== Command: ./test
==29640== 

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): 65535
Enter main memory 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
==29640== Invalid write of size 4
==29640==    at 0x400B25: write_cache(int*, _tag_cache*, int, int, int) (test.cc:173)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac4bc is 0 bytes after a block of size 262,140 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x400968: init_main_mem_of(int) (test.cc:122)
==29640==    by 0x400824: program() (test.cc:71)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
==29640== Invalid read of size 4
==29640==    at 0x400B34: write_cache(int*, _tag_cache*, int, int, int) (test.cc:175)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac8f0 is 0 bytes after a block of size 1,008 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x4009C8: init_cache_of(int) (test.cc:132)
==29640==    by 0x400832: program() (test.cc:72)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
Write miss!
==29640== Invalid write of size 4
==29640==    at 0x400B5C: write_cache(int*, _tag_cache*, int, int, int) (test.cc:178)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac8f0 is 0 bytes after a block of size 1,008 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x4009C8: init_cache_of(int) (test.cc:132)
==29640==    by 0x400832: program() (test.cc:72)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
==29640== Invalid read of size 8
==29640==    at 0x400B6B: write_cache(int*, _tag_cache*, int, int, int) (test.cc:181)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac8f8 is 8 bytes after a block of size 1,008 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x4009C8: init_cache_of(int) (test.cc:132)
==29640==    by 0x400832: program() (test.cc:72)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
==29640== Invalid write of size 8
==29640==    at 0x400BA5: write_cache(int*, _tag_cache*, int, int, int) (test.cc:185)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac8f8 is 8 bytes after a block of size 1,008 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x4009C8: init_cache_of(int) (test.cc:132)
==29640==    by 0x400832: program() (test.cc:72)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
==29640== Invalid read of size 8
==29640==    at 0x400BBF: write_cache(int*, _tag_cache*, int, int, int) (test.cc:189)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac8f8 is 8 bytes after a block of size 1,008 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x4009C8: init_cache_of(int) (test.cc:132)
==29640==    by 0x400832: program() (test.cc:72)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
==29640== Invalid read of size 4
==29640==    at 0x400BE4: write_cache(int*, _tag_cache*, int, int, int) (test.cc:189)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac4bc is 0 bytes after a block of size 262,140 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x400968: init_main_mem_of(int) (test.cc:122)
==29640==    by 0x400824: program() (test.cc:71)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
==29640== Invalid read of size 8
==29640==    at 0x400C06: write_cache(int*, _tag_cache*, int, int, int) (test.cc:192)
==29640==    by 0x400878: program() (test.cc:80)
==29640==    by 0x4006CC: main (test.cc:29)
==29640==  Address 0x59ac8f8 is 8 bytes after a block of size 1,008 alloc'd
==29640==    at 0x4C24660: malloc (vg_replace_malloc.c:195)
==29640==    by 0x4009C8: init_cache_of(int) (test.cc:132)
==29640==    by 0x400832: program() (test.cc:72)
==29640==    by 0x4006CC: main (test.cc:29)
==29640== 
Word 15 of block 63 with tag 63 contains 14

Main memory to cache memory mapping: 
------------------------------------ 
1) Set parameters 
2) Read cache 
3) Write to cache 
4) Exit 

Enter selection: ^C==29640== 
==29640== HEAP SUMMARY:
==29640==     in use at exit: 263,212 bytes in 3 blocks
==29640==   total heap usage: 5 allocs, 2 frees, 526,380 bytes allocated
==29640== 
==29640== LEAK SUMMARY:
==29640==    definitely lost: 64 bytes in 1 blocks
==29640==    indirectly lost: 0 bytes in 0 blocks
==29640==      possibly lost: 0 bytes in 0 blocks
==29640==    still reachable: 263,148 bytes in 2 blocks
==29640==         suppressed: 0 bytes in 0 blocks
==29640== Rerun with --leak-check=full to see details of leaked memory
==29640== 
==29640== For counts of detected and suppressed errors, rerun with: -v
==29640== ERROR SUMMARY: 23 errors from 8 contexts (suppressed: 4 from 4)

You were simply lucky that it didn't crash with other compilers, but you did indeed have an error (you don't check that user input is sane!)

At the very least, perhaps you should put something like this before main_mem_ptr[addr] = value;:

assert(addr < main_mem_size); 


You always can get information about crash, if you run your program under source level debugger - gdb.

Compile your sources with -g option and run it under gdb.

$gdb ./your_prog_name_here

In gdb type "run" to start program.

When program crashed gdb will stop. Type "bt" to get backtrace of your executable to get an idea which statement cause crash.

Hope this help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜