Skip navigation

Monthly Archives: June 2008

I had this problem recently:

JVM terminated. Exit code=-1
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m
-XX:MaxPermSize=256M
-Djava.class.path=C:\Program Files\eclipse\plugins\org.eclipse.equinox.launcher_1.0.100.v20080509-1800.jar
-os win32
-ws win32
-arch x86
-showsplash C:\Program Files\eclipse\\plugins\org.eclipse.platform_3.3.100.v200806172000\splash.bmp
-launcher C:\Program Files\eclipse\eclipse.exe
-name Eclipse
–launcher.library C:\Program Files\eclipse\plugins\org.eclipse.equinox.launcher.win32.win32.x86_1.0.100.v20080509-1800\eclipse_1114.dll
-startup C:\Program Files\eclipse\plugins\org.eclipse.equinox.launcher_1.0.100.v20080509-1800.jar
-vm C:\Program Files\Java\jre1.6.0_06\bin\client\jvm.dll
-vmargs
-Xms40m
-Xmx512m
-XX:MaxPermSize=256M
-Djava.class.path=C:\Program Files\eclipse\plugins\org.ecipse.equinox.launcher_1.0.100.v20080509-1800.jar

here’s the fix

My laptop computer only has 512MB of ram available. I don’t have all that much disk space either. It seems that Eclipse wanted 512MB of xmx memory.. So i just opened C:\Program Files\eclipse\eclipse.ini and changed the amount of xmx to 256MB, which my system should be able to handle.

check it out:

class Fraction
{
private:
  int num, den;
public:
  Fraction() : num(1), den(1) { }

  // overloading the () operator for the Fraction object.
  // you can pass parameters, or return a type from this func as well
  void operator()( void )
  {
    printf("operator().\n");
    printf("I'm what happens when you invoke this object AS a function\n");
    printf("Can you think of some really cool uses for me???  I think you can.");
  }
};

int main()
{
  Fraction f;
  f();    // invoke the Fraction object. . . NEATO!!!  
  return 0;
}

In C, when you define an array like:

int a[2][3];

DOES C consider that as 2 arrays of 3 ints, or is it 3 arrays of 2 ints?

I’ll tell you the answer soon .

.
.
.
.

But you have to guess first.

.
.
.
.
.
.

Ok.

IT IS TWO arrays of THREE ints. You read it from left to right.

So, if we define:

int a[2][3] = {
 { 3, 5, 7 },
 { 9, 1, 0 }
} ;

We know that’s right because if we tried to do it any other way, (like

 int a[2][3] = {
 { 9, 9 },
 { 9, 0 },
 { 2, 2 }
} ;

) we’d get something like “error: too many initializers” from the C compiler. That’s because this HAS TO BE an array of TWO arrays of THREE ints each.

ok ok but what about row major vs column major?

Row major vs column major really has to do with whether you think of a matrix as a collection of row vectors (“row major”), or if you prefer to think of a matrix as a collection of COLUMN VECTORS (aka “column major”).

Let’s start with column major.

interpreting the matrix as column major

So, don’t forget, we had:

int a[2][3] = {
 { 3, 5, 7 },
 { 9, 1, 0 }
} ;

If we’re thinking COLUMN MAJOR, then we will understand this to be 2 COLUMN VECTORS, WITH 3 ENTRIES EACH.

SO, we’d visualize the array as:

3 9
5 1
7 0

interpreting the matrix as ROW MAJOR

If we were to think of that same matrix:

int a[2][3] = {
 { 3, 5, 7 },
 { 9, 1, 0 }
} ;

If we’re thinking ROW MAJOR, then we will understand this to be 2 __ROW__ VECTORS, WITH 3 ENTRIES EACH.

So we’d visualize:

3 5 7
9 1 0

dealing with both types

Ok so notice the COLUMN MAJOR matrix was like:

3 9
5 1
7 0

and the ROW MAJOR was like:

3 5 7
9 1 0

So, let’s notice a few things that are interesting.

Notice that the original data was:

int a[2][3] = {
 { 3, 5, 7 },
 { 9, 1, 0 }
} ;

Now, notice this. The COLUMN MAJOR version has the values go inside it IN ORDER, DOWN THE COLUMNS.

3 9
5 1
7 0

The ROW MAJOR version has the values go inside it, IN ORDER, DOWN THE ROWS.

3 5 7
9 1 0

accessing and modifying values of row major and column major mats

If you’re accessing the COLUMN MAJOR matrix, you’d write something like:

a[1][2] = 99;  // set a[COL=1][ROW=2] TO 99;
// In the COLUMN MAJOR MATRIX,
// the specification of the COLUMN to hit
// comes first.
3 9
5 1
7 99

If you’re accessing the ROW MAJOR matrix, you’d write something like:

a[1][2] = 2000;  // set a[ROW=1][COL=2] TO 2000;
// In the ROW MAJOR matrix,
// specification of the ROW to hit
// comes first.
3 5 7
9 1 2000

BUT NOTICE, in the two green examples, we are HITTING THE SAME ENTRY IN THE MATRIX.

accessing a 1D array as row major, or column major

SAY you stored the matrix values in a 1D array.

int m[6] = {3,5,7,9,1,0};

Results in something like:

3 5 7 9 1 0

in C memory.

If you want to treat this 1D array as a COLUMN MAJOR matrix, you’d access it like this:

A[col][row] = A[row + col*NUMROWS];

If you want to treat this 1D array as a ROW MAJOR matrix, you’d access it like this:

A[row][col] = A[col + row*NUMCOLS];

This is some code that stores the values passed to a variadic function in a stack-like <vector>.

Each va_list argument that got passed in the place of … will be saved as a va_item in the va_stack vector.

It preserves the original datatype in va_item.datatype as just a character string. The actual data is stored with a generic pointer (type void*) in va_item.data.


//////////////////////////////////////////
//                                      //
// VARIABLE ARGUMENT LISTS ## revisited //
//                                      //
// You found this at bobobobo's weblog, //
// https://bobobobo.wordpress.com        //
//                                      //
// Creation date:  June 4/08            //
// Last modified:  June 4/08            //
//                                      //
//////////////////////////////////////////
//
// This code file is the result of comments
// by Ran.

// It is supposed to be some code that can
// save off the values that are passed to
// a variadic function ( a variadic function
// is just a function that accepts the ...
// variable number of arguments).

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#include <vector>
using namespace std;


// Some defs.
#define  CHAR           "char"
#define  INT            "int"
#define  FLOAT          "float"
#define  DOUBLE         "double"
#define  STRING         "char *"
#define  BOBBLEDEBOOP   "BobbledeBoop"


// Some protos.
void saveThem_using_va_arg( char * argsfmt, ... );
int getSizeOfDataType( char * datatype );
char * getDatatypeString( char datatype );


// some object, for testing purposes
struct BobbledeBoop
{
    int a, b, c, d;
    float x, y, z, w;

    void print()
    {
        printf("bobble bobble bobble %d %d %d %d %.2f %.2f %.2f %.2f\n",
                a,b,c,d,x,y,z,w );
    }
};

struct va_item
{
    const static int MAX_TYPE_NAME_LENGTH = 32;
    // 32 chars max length for datatype
    
    char datatype[ MAX_TYPE_NAME_LENGTH ];
    
    void * data;    // generic pointer.
    // this pointer will actually hold
    // the data itself.
};




// typedefs
typedef   vector<va_item *>               va_stack ;
typedef   vector<va_item *>::iterator     va_stack_iterator ;




//////////////////
// globs
// declare a global va_stack
va_stack stack;



int main()
{
    // test the code.

    saveThem_using_va_arg( "%d %s %t %c", 20, "a string", 247.5546, 'x' );
    saveThem_using_va_arg( "%d %d %t %c", 20, 90, 247.5546, 'x' );
    saveThem_using_va_arg( "%s %s %d %c",
        "some text data",
        "and then some more text data",
        30000,
        'b' );
   
    BobbledeBoop bbd;
    bbd.a = 110;
    bbd.b = 220;
    bbd.c = 330;
    bbd.d = 440;
    bbd.x = 110.1;
    bbd.y = 220.2;
    bbd.z = 330.3;
    bbd.w = 440.4;

    saveThem_using_va_arg( "%B", bbd );

    bbd.x = 20000;
    saveThem_using_va_arg( "%B", bbd );

    saveThem_using_va_arg( "%c %B %d", 'r', bbd, 2000 );
    saveThem_using_va_arg( "%c %t %d", 'r', 299.944, 2000 );

    /////////
    // print.
    for( va_stack_iterator it = stack.begin();
         it != stack.end();
         ++it )
    {
        char * datatype = (*it)->datatype;
        printf( "datatype:  %s\n", datatype );

        // its necessary to reinterpret the void* pointer
        // before attempting to dereference it.
        if( strcmp( datatype, CHAR ) == 0 )
        {
            // char data.
            printf("data:  %c\n", *(reinterpret_cast<char *>( (*it)->data ) ));
        }        
        else if( strcmp( datatype, INT ) == 0 )
        {
            printf("data:  %d\n", *(reinterpret_cast<int *>( (*it)->data ) ));
        }
        else if( strcmp( datatype, FLOAT ) == 0 )
        {
            printf("data:  %f\n", *(reinterpret_cast<float *>( (*it)->data ) ));
        }
        else if( strcmp( datatype, DOUBLE ) == 0 )
        {
            printf("data:  %f\n", *(reinterpret_cast<double *>( (*it)->data ) ));
        }
        else if( strcmp( datatype, STRING ) == 0 )
        {
            printf("data:  %s\n", (reinterpret_cast<char *>( (*it)->data ) ));
        }
        else if( strcmp( datatype, BOBBLEDEBOOP ) == 0 ) // BobbledyBoop object
        {
            printf("data:  " );
            (reinterpret_cast<BobbledeBoop *>( (*it)->data ) )->print();

        }
        printf("\n");
    }

    return 0;
}


/// Accepts a format string
/// and a va_list and saves
/// them to the global va_stack 'stack'
void saveThem_using_va_arg( char * argsfmt, ... )
{
    va_list listPointer;

    va_start( listPointer, argsfmt );

    // fetch type from fmt string
    char * next = strchr( argsfmt, '%' );

    do // while there's another %...
    {
        va_item * item = (va_item*)malloc(sizeof(va_item));   // declare a new va_item.

        // get the next char, which tells
        // what kind of data it is.
        char ctype = next[1];
        
        char * datatype = getDatatypeString( ctype );

        strcpy( item->datatype, datatype );  //save datatype in the va_item.

        int datalength = getSizeOfDataType( datatype );
        if( datalength == 0 ) {
            printf("FATAL ERROR: I didn't know datatype %s\n", datatype);
            return;
        }

        //save undying ref to data in va_item.
        item->data = (void*)malloc( datalength );


        // retrieve and copy the data.
        if( strcmp( datatype, CHAR ) == 0 )
        {
            char data = va_arg( listPointer, char );
            memcpy( item->data, &data, datalength );
        }        
        else if( strcmp( datatype, INT ) == 0 )
        {
            int data = va_arg( listPointer, int );
            memcpy( item->data, &data, datalength );
        }
        else if( strcmp( datatype, FLOAT ) == 0 )
        {
            float data = va_arg( listPointer, float );
            memcpy( item->data, &data, datalength );
        }
        else if( strcmp( datatype, DOUBLE ) == 0 )
        {
            double data = va_arg( listPointer, double );
            memcpy( item->data, &data, datalength );
        }
        else if( strcmp( datatype, STRING ) == 0 )
        {
            char * data = va_arg( listPointer, char * );

            datalength = strlen(data);

            // special case for string.  longer data region.
            // reallocate.
            free( item->data );

            item->data = (void*)malloc( datalength );

            strcpy( (char*)item->data, data );
        }
        else if( strcmp( datatype, BOBBLEDEBOOP ) == 0 ) // BobbledyBoop object
        {
            BobbledeBoop data = va_arg( listPointer, BobbledeBoop );
            memcpy( item->data, &data, datalength );
        }
        else
        {
            printf("I didn't know the type %s.\n", datatype );
            return; // type not known, so . . . 
        }

        
        // push that new item onto the stack.
        stack.push_back( item );

        
    } while( next = strchr( next+1, '%' ) ); // next item


    va_end( listPointer );

}


int getSizeOfDataType( char * datatype )
{
    if( strcmp( datatype, CHAR ) == 0 )
    {
        return sizeof( char );
    }        
    else if( strcmp( datatype, INT ) == 0 )
    {
        return sizeof( int );
    }
    else if( strcmp( datatype, FLOAT ) == 0 )
    {
        return sizeof( float );
    }
    else if( strcmp( datatype, DOUBLE ) == 0 )
    {
        return sizeof( double );
    }
    else if( strcmp( datatype, STRING ) == 0 )
    {
        return sizeof( char * );
    }
    else if( strcmp( datatype, BOBBLEDEBOOP ) == 0 ) // BobbledyBoop object
    {
        return sizeof( BobbledeBoop ); // return the size of the BobbledyBoop object
    }
    else
    {
        printf("I didn't know the type %s.\n", datatype );
        return 0; // type not known, so . . . 
    }
}

char * getDatatypeString( char datatype )
{
    switch( datatype )
    {
    case 'c':
        return CHAR;
        break;
    case 'd':
        return INT;
        break;
    case 'f':
        return FLOAT;
        break;
    case 't':
        return DOUBLE;
        break;
    case 's':
        return STRING;
        break;
    case 'B':
        return BOBBLEDEBOOP;
        break;
    default:
        printf("I didn't know the type %c.\n", datatype );
        return 0;
    }
}
/* 
     ____   __   __      __   __  ___
    / _  \ /  / /  /    /  /  \ \/  /
   / _/ / /  / /  /    /  /    \   /
  / _/ \ /  / /  /__  /  /__   /  /
 /_____//__/ /______//______/ /__/

*/

code on esnips!

Well, everyone knows programming in C is fun.

I think the reason people hate it sometimes, and the reason for the pretty much WHY C and C++ is being pushed out/taken over by programming languages that offer automatic memory management such as Java and C#, is that anything less than absolute PERFECT memory management when programming in C will result in some pretty tough bugs.

Hard to find, deeply rooted, strange and erratically behaving BUGS.

For instance, take this line of code:

va_item * item = (va_item*)malloc(sizeof(item)); /* declare a new va_item */

Do you see anything wrong with it?

How now?

va_item * item = (va_item*)malloc(sizeof(va_item)); /* declare a new va_item */

So the top line has a very subtle mistake in it that is very easy to miss. item was only getting 4 bytes allocated to it instead of the 36 bytes its supposed to get for being a va_item.

And it produced a bug in the code that was very erratic and strange. It seemed to be more prominent in release builds than debug builds, and would result in really corrupted data (of course).

I guess keyword new in C++ might have saved the day pre-emptively here because it would have flagged that item isn’t a datatype.

But anyway.

I guess the moral of the post is: when you see weird and erratic bugs in your C programs, check ALL your mallocs that you have written recently!!!

I’ve had this question for a while now.

On win32, using Visual Studio, the following program doesn’t work:

#include <stdlib.h>
#include <stdio.h>

void makeArray( char * arr, int dim )
{
  arr = (char *)malloc( dim*sizeof(char) );
}
void printArray( char * arr, int dim )
{
  for( int i = 0; i < dim; i++ )
  {
    printf( "%d ", arr[i] );
  }
}

int main()
{
  char * arr = NULL;
  makeArray( arr, 10 );
  printArray( arr, 10 );
}

You get that arr is still NULL, even after you call makeArray() on it.

However, this does work as expected:

#include <stdlib.h>
#include <stdio.h>

void makeArray( char * & arr, int dim )
{
  arr = (char *)malloc( dim*sizeof(char) );
}
void printArray( char * arr, int dim )
{
  for( int i = 0; i < dim; i++ )
  {
    printf( "%d ", arr[i] );
  }
}

int main()
{
  char * arr = NULL;
  makeArray( arr, 10 );
  printArray( arr, 10 );
}

Using C++’s & to make the variable arr inside makeArray() an alias to the char * pointer that is passed from main.

My question is, why doesn’t the first program work? I just don’t see why it is required to use & when the array should be passed by reference.

Anybody got a clue?