I am importing some C code into a C++ compiler, specifically Borland C++ Builder 5. I seem to have a problem with this style of code:

// A structure that contain's itself
typedef struct AnObject AnObject;

struct AnObject {
    AnObject *Object;
};

// A global structure to store a pointer of the AnObject structure
typedef struct {
    AnObject  *Page;
} _Stock;

_Stock Stock;

// A function that returns an instance of AnObject
AnObject *CreateInstance() {
    return malloc(sizeof(AnObject));
}

// A function that copies the generated instance to the global pointer
void somefunct() {
    // The pointer will start off NULL
    Stock.Page = NULL;

    // The pointer should now receive a non-NULL pointer
    Stock.Page = CreateInstance();
}

In GCC, the Stock.Page pointer will be non-NULL at the end of the somerfunct() function. This is not the case for Borland C++ Builder 5. In that case Stock.Page continues to be NULL.

On the other hand, if I change somefunct() to this...

void somefunct() {
    // The pointer will start off NULL
    Stock.Page = NULL;

    // Borland C++ Builder 5 likes this syntax. TempPage is a non-NULL.
    AnObject *TempPage = CreateInstance();

    // But I still cannot copy the pointer from TempPage.
    Stock.Page = TempPage;

    // Stock.Page is still NULL at this point!
}

Since I am better versed in the C language, I am thinking that this is some kind of incompatibility with the language itself, and that I need to do this more C++ style. On the other hand, the compiler I am using is quite old and this could be some kind of bug. Does anyone here know what I might be doing wrong?

Hmm, interesting. Two things to consider since there's some potential funkiness involved. When you call malloc(), make sure that the correct header is included, and also cast the result as C++ doesn't support implicit conversion from void*. This is all speculation since I haven't used a Borland compiler in ages, but it could be that the lack of a matching definition causes the compiler to assume this:

int malloc(size_t)
{
    return 0;
}

Granted that's unlikely, but it would explain your results. At the very least, making sure the code is C++ compatible would be a start in troubleshooting the issue. :)

Thank you for your quick reply deceptikon. The problem with your theory is that the TempPage variable worked fine using malloc(). The problem appears to be in copying the pointer to the actual Stock.Page pointer. Also, I use malloc() in other places of the code (such as creating space for strings and arrays) and that works fine.

Other parts of the code work fine in the C++ compiler. So far this seems to be the main incompatibility.

By the way, you are right about the casting issue. I mistyped the code in my post. It was actually more like this in my real world example:

AnObject *CreateInstance() {
    return (AnObject *)malloc(sizeof(AnObject));
}

Like I said, it was a very unlikely theory. ;) In the actual code, are you by any chance calling somefunct() from a constructor in a global object?

In this case its being called by a VCL button OnClick event handler. The code itself is in a cpp file compiled with the rest of the project. As an event handler, I doubt it is a constructor.

How would that matter?

Since constructors can run before main() in C++, order of construction can sometimes be an issue with global and static objects that touch each other. Unfortunately, I'm as stumped as you are, probably more so in that I'm so far disconnected from the actual running code. ;)

Apologies.

I fixed the problem by changing line 13 of my main posted code to this:

static _Stock Stock;

Do keep in mind that my actual code is composed of literally thousands of lines of code spanning many cpp/h files. Apparently Borland C++ Builder 5 does not like working with structures defined in headers unless its anchored down with the static keyword.

I guess thats good information.

Correction: The fix appears to be that I need to use the extern keyword instead of static, then declare it in a CPP file. The problem seems to be with the structure being created in different contexts or address spaces for each loaded CPP file or something. Might be a Borland C++ Builder specific issue.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.