Gamemaker, Assembler & C++

This might be very specific. So I don't really "expect" some direct answers here, but any help (as long as it's correct) is helpful..

I used to program in GameMaker, and I like it still, now a new library is made to incorporate gamemaker functions inside a C++ program: very usefull for direct communication!
[url=http://gmc.yoyogames.com/index.php?showtopic=420970]here is the topic about it[/url]

Now the first code allocates memory for the "string-part" of a variable by calling 'malloc'. So I had to do a small rewrite of the GMVariable class which now looks like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class GMVariable
{
private:
    int type;
    double real;
    char* string;
    int padding;
public:
    GMVariable();
    GMVariable(double a);
    GMVariable(int a);
    GMVariable(char* a);
    GMVariable(std::string a);

    GMVariable(const GMVariable& v);
    ~GMVariable();

    operator double();
    operator char*();
    GMVariable const operator-(const GMVariable& v );
    GMVariable const operator+(const GMVariable& v );
    GMVariable const operator*(const GMVariable& v );

    GMVariable& operator=(const GMVariable& v);

    bool isReal();
    bool isString();
};
The default constructor:
1
2
3
4
5
6
7
GMVariable::GMVariable()
{
    type = 0;
    real = 0;
    string = 0;
    padding = 0;
}
One of the other constructors now works like this:
1
2
3
4
5
6
7
8
9
10
GMVariable::GMVariable(std::string a) {
    char* n;
    n = (char*) malloc(a.length() + 5);
    *((unsigned int*)n) = a.length();
    strcpy(n + 4, a.c_str());
    type = 1; //type (0,1) means whether it's a real(0) or string(1)
    real = 0; //real part
    string = n + 4; //string part (length followed by a c-style-string)
    padding = 0;
}
And the destructor looks like:
1
2
3
4
5
GMVariable::~GMVariable() {
    if (this->string != NULL) {
        free(string-4);
    }
}

Copy constructors (and all other constructors) work correctly with allocating the memory which is needed etc.

The problem however is in this function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    GMVariable ExternalCall(GMPROC* proc, int argsUsed, int argCount, GMVariable* args)
    {
        GMVariable ret;
        if(argCount < 15) argsUsed = 0;
        DWORD t; t = (DWORD)&ret;
        __asm
        {
            push (args);
            push (argCount);
            push (t);
            mov ecx, (argsUsed);
            call (proc)
        };
        return ret;
    }

Above function is called when you try to execute a "gamemaker-native-function".
GMPROC* proc = a pointer to a procedure of a gamemaker function.
int argsUsed, int argCount = Number of arguments the gamemaker function takes
GMVariable* args = an array filled with "GMVariable" objects..

Firstly it constructs GM-Variable with the default constructor.. But afterwards the object is filled by the ASM (especiall the "call (proc)", which executes the GameMaker function).

And the variables are (for example:)
type = 0;
real = 0;
string = "5";
padding = 0;

Also the memory (4 positions) before the "string" are set correctly:
int i = *(string-4); sets "i" to the length of the string (1 in above example)..

However when it's going out of above function: and thus destroying "ret", it crashes complaining about a corruption of the heap! - This happens exactly at the "free()" command of the destructor.

So my question is:
How to "free" the memory allocated by the assembly? - Or is it freed automatically?


Does the function called by the "call (proc)" instruction expect that "t" be a pointer to
memory that is laid out exactly like the data members of your GMVariable class?
why -4 for free(string-4);?
Because of lines 3 and 8.
Topic archived. No new replies allowed.