typecasting pointer issues

P

PapaTodd

Greetings all,

I've been fighting with this issue all day. This code is tried and
true on other OS's, but when I compile and test on AIX 5.3 using xlC_r,
I have problems.

Here is the code snippets giving a problem:


main.cpp
---------------------------------
mySchemaType *theSchema = NULL; // declared as global

// within main()
theSchema = prepareSchemaAndFilters(some strings showing files);

pRecord = theSchema->records;
pField = pRecord->fields;
mySpecificType *tmpRecord = (mySpecificType *)pField->specific;
printf("the specific db_type = %s\n",tmpRecord->db_type);

----------------------------------
At this point, db_type is shown to be garbage. This is my problem.
Here is what prepareSchemaAndFilters looks like:

makeschema.c
----------------------------------
mySchemaType *prepareSchemaAndFilters(the file strings)
{
mySchemaType *theSchema;
// code removed for clarity, essentially items are put into theSchema
myRecordType *pRecord = theSchema->records;
myFieldType *pField = pRecord->fields;
mySpecificType *tmpRecord = (mySpecificType *)pfield->specific;
printf("the specific db_type = %s\n",tmpRecord->db_type);

return theSchema;
}
----------------------------------
Within makeschema.c, the specific db_type is output the expected value.

Here are the type definitions:
schema.h
----------------------------------
typedef struct my_record myRecordType;
typedef struct my_field myFieldType;
typedef struct my_schema mySchemaType;
typedef struct my_specific mySpecificType;

struct my_specific {
char name[256];
char db_type[256];
int db_length;
void *additional_specific;
refKey* firstRefKey;
refKey* lastRefKey;
};

struct my_field {
char* name;
char* my_name;
myFieldType* fields;
bool is_key;
bool is_binary;
bool is_single;
FilterType filter;
void* specific;
stringList* values;
myFieldType* next;
}

struct my_record {
char* name;
char* my_name;
myFieldType* fields;
FilterType filter;
void* specific;
int seqno;
myRecordType* next;
int updateNumber;
};

struct my_schema {
mesRecord* records;
void* specific;
};

-------------------------------

So, finally to the source of my problem. When I am within mes_schema.c
(linked in as a library), I can cast the void* as a specific* and get
the different values. When I am back in main.cpp, if I do this, the
values that are part of specific* print correctly.

This appears to be a pointer error, and I suspect any of the following
possibilities:
1) Even though I'm explicitely compiling under 32-bit mode, somehow the
pointers are not being handled properly.
2) Some weird translation between the .c library and the .cpp file? We
are using an extern "C" { flag for the .c files, but maybe this isn't
good enough when we compile?

As I mentioned before, on this system (AIX 5L), we are seeing this
problem. On all others (HP-UX, Win, Solaris), we don't.

Any advice would be appreciated. Tonights task is to start wading
through dbx to verify that it is an invalid pointer issue, but if I
verify that, I'm not sure what the fix is going to be.

Thanks in advance,

Todd
 
A

Alf P. Steinbach

* (e-mail address removed):
I've been fighting with this issue all day. This code is tried and
true on other OS's, but when I compile and test on AIX 5.3 using xlC_r,
I have problems.

Here is the code snippets giving a problem:


main.cpp

That's the first problem, and the solution is: DON'T USE GLOBAL
VARIABLES.


// within main()
theSchema = prepareSchemaAndFilters(some strings showing files);

pRecord = theSchema->records;
pField = pRecord->fields;
mySpecificType *tmpRecord = (mySpecificType *)pField->specific;

That's a second problem: you're doing a reinterpret_cast using C
notation so you don't know what it is, and the solution is: USE C++
STYLE CASTS IF YOU ABSOLUTELY MUST CAST.

And the casting is a third problem, for which the solution is DON'T USE
CASTS.

printf("the specific db_type = %s\n",tmpRecord->db_type);

Not surprising; see above.

This is my problem.
Here is what prepareSchemaAndFilters looks like:

makeschema.c
----------------------------------
mySchemaType *prepareSchemaAndFilters(the file strings)
{
mySchemaType *theSchema;
// code removed for clarity, essentially items are put into theSchema
myRecordType *pRecord = theSchema->records;
myFieldType *pField = pRecord->fields;
mySpecificType *tmpRecord = (mySpecificType *)pfield->specific;
printf("the specific db_type = %s\n",tmpRecord->db_type);

return theSchema;
}

You don't show enough code to diagnose the technical problem, in
particular you don't show the earlier assignment to 'pfield->specific'.

Why did you think the relevant code would not matter?

However, what you show is enough to diagnose the real problem, which is:
assembly language level coding (expressed in C or C++ doesn't matter).

[snip]
So, finally to the source of my problem. When I am within mes_schema.c
(linked in as a library), I can cast the void* as a specific* and get
the different values. When I am back in main.cpp, if I do this, the
values that are part of specific* print correctly.

?

Anyway, sound like you have a pointer pointing to deallocated storage,
nowhere in particular, or the stack.
 
T

Todd

Alf said:
* (e-mail address removed):
I've been fighting with this issue all day. This code is tried and
true on other OS's, but when I compile and test on AIX 5.3 using xlC_r,
I have problems.

Here is the code snippets giving a problem:


main.cpp

That's the first problem, and the solution is: DON'T USE GLOBAL
VARIABLES.


// within main()
theSchema = prepareSchemaAndFilters(some strings showing files);

pRecord = theSchema->records;
pField = pRecord->fields;
mySpecificType *tmpRecord = (mySpecificType *)pField->specific;

That's a second problem: you're doing a reinterpret_cast using C
notation so you don't know what it is, and the solution is: USE C++
STYLE CASTS IF YOU ABSOLUTELY MUST CAST.

And the casting is a third problem, for which the solution is DON'T USE
CASTS.

printf("the specific db_type = %s\n",tmpRecord->db_type);

Not surprising; see above.

This is my problem.
Here is what prepareSchemaAndFilters looks like:

makeschema.c
----------------------------------
mySchemaType *prepareSchemaAndFilters(the file strings)
{
mySchemaType *theSchema;
// code removed for clarity, essentially items are put into theSchema
myRecordType *pRecord = theSchema->records;
myFieldType *pField = pRecord->fields;
mySpecificType *tmpRecord = (mySpecificType *)pfield->specific;
printf("the specific db_type = %s\n",tmpRecord->db_type);

return theSchema;
}

You don't show enough code to diagnose the technical problem, in
particular you don't show the earlier assignment to 'pfield->specific'.

Why did you think the relevant code would not matter?

However, what you show is enough to diagnose the real problem, which is:
assembly language level coding (expressed in C or C++ doesn't matter).

[snip]
So, finally to the source of my problem. When I am within mes_schema.c
(linked in as a library), I can cast the void* as a specific* and get
the different values. When I am back in main.cpp, if I do this, the
values that are part of specific* print correctly.

?

Anyway, sound like you have a pointer pointing to deallocated storage,
nowhere in particular, or the stack.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

My general excuse for some of the sloppy coding is that it is
inherited. Not that I'm a great programmer, but... anyway, moving
forward.

First test: change the returned variable theSchema to a local. Didn't
help.
Second test: change the void* to specific* in the structure
declaration. Didn't help.

So I'm beginning to think that the problem is that the original setting
of the values isn't being handled well, and it is just luck that it
worked on all of our other products/platform combinations.

I don't want this to turn into a "fix my program one step at a time for
me", so I'm going to spend another day debugging it tomorrow. The code
that initially sets the values that are read from the file appear to be
correct at first glance, doing things such as allocating memory, then
setting the values, or duplicating the strings via an inline function.

Thanks for your help,

Todd
 
A

Alf P. Steinbach

* Todd:
First test: change the returned variable theSchema to a local. Didn't
help.
Second test: change the void* to specific* in the structure
declaration. Didn't help.

Did you also remove _all_ the casts?

They can be difficult to spot.

Hiding themselves away in innocent-looking code, like gremlins... ;-)
 
S

savagesmc

In prepareSchemaAndFilters, is there some code that allocates some
memory for a concrete type into the void* (pfield->specific) and loads
values into it? Also, you should show the code that allocates the
mySchema in general.

Need more sample code.
 
K

Kaz Kylheku

Alf said:
That's a second problem: you're doing a reinterpret_cast using C
notation so you don't know what it is, and the solution is: USE C++
STYLE CASTS IF YOU ABSOLUTELY MUST CAST.

No, you want static_cast here. A void * pointer is being used as a
generic handle on some variant data.

The best way to handle that is to take advantage of the implicit
conversion /to/ the void *, and use static_cast to do the reverse of
that implicit conversion.

Yes, try to use a C++ cast but don't choose a stronger cast, or
combination of casts, than what the traditional notation would
choose!!!

:)
 
A

Alf P. Steinbach

* Kaz Kylheku:
No, you want static_cast here.

A static cast is a C++ style cast, so what does the "no" refer to?

If the conversion to and back from void* is not a reinterpret_cast in
disguise, then the void* isn't needed, and is meaningless.

Therefore, I think the void* is a reinterpret_cast in disguise.
 
G

Greg Comeau

* Kaz Kylheku:

A static cast is a C++ style cast, so what does the "no" refer to?

He means to use static_cast in this case over reinterpret_cast.
If the conversion to and back from void* is not a reinterpret_cast in
disguise, then the void* isn't needed, and is meaningless.

Therefore, I think the void* is a reinterpret_cast in disguise.

This one's a funny one. In cases where you're converting to
a void * and back, I would say that static_cast is preferred.
 
S

savagesmc

I thought the key comment in the original post was that the casting
worked from main, but not in the function just before the return.
Changing the style of casting doesn't seem like it would have anything
to do with that type of observed behavior. It seems to me that there
is more of a pointer problem somewhere, which is why I suggested it
might be nice to see the other parts of the hcode that go with that
example.

Unless one of you more experienced c++ guys can explain how doing a
cast in a function can give a different answer than doing the same
exact cast in the scope where the function was called.

Steve
 
O

Old Wolf

Greetings all,

I've been fighting with this issue all day. This code is tried
and true on other OS's, but when I compile and test on AIX 5.3
using xlC_r, I have problems.

Here is the code snippets giving a problem:
mySpecificType *tmpRecord = (mySpecificType *)pField->specific;

Perhaps pField->specific is not correctly aligned for a
pointer to mySpecificType.

Can you post the code where pField->specific is given its value?

For debugging, you could try printing out the void pointer and
then printing out the casted pointer, that might give you a clue
as to what happened.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top