Code worked under Windows NT, does not work under QNX.

Hi everybody,

I am working on a multitasking C++ project in QNX 4.25. One of the tasks was
developed under Windows NT and fully unit tested. Its integration with the
other tasks (these were developed with Watcom 10.6 under QNX 4.23 and have
been working in a different context for years) was also tested under Windows
NT, however, using simulation software that mimicked the behaviour of these
tasks through their interface descriptions. Everything was fine. Then came
the time when I needed to port the application to the target platform. I
recompiled and linked the Windows-developed code with Watcom 10.6 under QNX
4.25. Then, I tried to run the application. The Windows-developed task would
run up to a certain point at which the application starts to create 35
objects on the heap (in a function, pointers to these dynamic objects are
created using the keyword “new”, which causes the class constructor to be
called, in which “calloc” is used to allocate memory for the newly created
object), the largest of which is 1600 Bytes in size; about half of these
objects are only 1 Byte in size.

I played with the HEAPSIZE, STACK, and OFFSET parameters in the call to the
linker (in the original makefile for the legacy tasks created for QNX 4.23
the values used for these parameters were 48K, 32K, 40K, respectively),
suspecting that the problem lay in how the compiler/linker created the
addresses for the code. The funny thing is, in some cases the task would
terminate at around the point where the 3rd or 4th object was being created;
in other cases, it would simply halt around the same area, without
terminating.

I would appreciate any comments on this situation.

Thank you,

Orhan.

Orhan Ozdengiz <orhan.ozdengiz@honeywell.com> wrote:

Hi everybody,

I am working on a multitasking C++ project in QNX 4.25. One of the tasks was
developed under Windows NT and fully unit tested. Its integration with the
other tasks (these were developed with Watcom 10.6 under QNX 4.23 and have
been working in a different context for years) was also tested under Windows
NT, however, using simulation software that mimicked the behaviour of these
tasks through their interface descriptions. Everything was fine. Then came
the time when I needed to port the application to the target platform. I
recompiled and linked the Windows-developed code with Watcom 10.6 under QNX
4.25. Then, I tried to run the application. The Windows-developed task would
run up to a certain point at which the application starts to create 35
objects on the heap (in a function, pointers to these dynamic objects are
created using the keyword “new”, which causes the class constructor to be
called, in which “calloc” is used to allocate memory for the newly created
object), the largest of which is 1600 Bytes in size; about half of these
objects are only 1 Byte in size.

I played with the HEAPSIZE, STACK, and OFFSET parameters in the call to the
linker (in the original makefile for the legacy tasks created for QNX 4.23
the values used for these parameters were 48K, 32K, 40K, respectively),
suspecting that the problem lay in how the compiler/linker created the
addresses for the code. The funny thing is, in some cases the task would
terminate at around the point where the 3rd or 4th object was being created;
in other cases, it would simply halt around the same area, without
terminating.

I would appreciate any comments on this situation.

Two likely causes – either you’re running out of available system
memory, that is, there isn’t enough memory to create the new objects,
or you’ve corrupted the heap in the program. That is, you have a bug
where you write before/after an allocated piece of memory, damaging/destroying
the information that the malloc library uses for handling this stuff.

The first is easier to determine than the second. In neither case
should you need to worry/play with any of HEAPSIZE, STACK or OFFSET
parameters to the linker – you’re not (likely) running of the end
of your stack, heap will grow dynamically, and OFFSET just changes the
base (virtual) address for your code.

If you do want to modify your stacksize (e.g. to increase it), use the
cc -N option for your link, rather than trying to modify the underlying
link variables directly.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Thank you David.

I do not think that running out of system memory is the cause as the system
has 128 MB of RAM and no user applications are running on it, only necessary
system processes (including TCP/IP) are.

As for the second possibility (i.e.corrupting the heap), I am wondering how
I would be doing that. I am not specifying explicit addresses anywhere. All
I do is asking for the system to give me some memory from somewhere on the
heap. Could you be kind enough to provide me some more insight on this?

In the meantime, I have stopped using the direct calls to the compiler and
the linker, and started using the cc utility w/o bothering about the heap
and stack sizes etc… did not work. Then, I tried to change the “calloc”
calls to "malloc"s… did not work, either.

I am not specifying any memory models, so, the application is compiled for
the small model, and linked for the flat model, by default. I am also not
specifying anything for the platform, so, 32-bit objects are created by
default (the processor is a Celeron).

The sad thing is that the application ran fine on Windows 2000. So, I am
inclined to rule out any bugs in the way memory is claimed from the heap. Of
course, I understand that there is a difference between how the heap is
managed by the Windows libraries and the Watcom/QNX libraries. But I am
helpless in dealing with this. Therefore, I would really appreciate some
more insight into how I might be “writing before/after an allocated piece of
memory, damaging/destroying the information that the malloc library uses for
handling this stuff”. Would allocating a big chunk of memory at once as
opposed to 35 steps of subsequent calls make a difference? The total amount
that is requested is below 17K anyway, not really a big amount of memory…

Thank you in advance for your further help.

Orhan.

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:al390j$alp$4@nntp.qnx.com

Two likely causes – either you’re running out of available system
memory, that is, there isn’t enough memory to create the new objects,
or you’ve corrupted the heap in the program. That is, you have a bug
where you write before/after an allocated piece of memory,
damaging/destroying
the information that the malloc library uses for handling this stuff.

The first is easier to determine than the second. In neither case
should you need to worry/play with any of HEAPSIZE, STACK or OFFSET
parameters to the linker – you’re not (likely) running of the end
of your stack, heap will grow dynamically, and OFFSET just changes the
base (virtual) address for your code.

If you do want to modify your stacksize (e.g. to increase it), use the
cc -N option for your link, rather than trying to modify the underlying
link variables directly.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Orhan Ozdengiz <orhan.ozdengiz@honeywell.com> wrote:

Thank you David.

I do not think that running out of system memory is the cause as the system
has 128 MB of RAM and no user applications are running on it, only necessary
system processes (including TCP/IP) are.

Had to check.

As for the second possibility (i.e.corrupting the heap), I am wondering how
I would be doing that. I am not specifying explicit addresses anywhere. All
I do is asking for the system to give me some memory from somewhere on the
heap. Could you be kind enough to provide me some more insight on this?

At this point that is what you’re doing – but if you’ve damaged the
heap at some point, it could crash at a later point.

In the meantime, I have stopped using the direct calls to the compiler and
the linker, and started using the cc utility w/o bothering about the heap
and stack sizes etc… did not work. Then, I tried to change the “calloc”
calls to "malloc"s… did not work, either.

They’re essentially the same – that is, they’ll end up doing the same
thing, but calloc will zero fill the memory after it gets it.

I am not specifying any memory models, so, the application is compiled for
the small model, and linked for the flat model, by default. I am also not
specifying anything for the platform, so, 32-bit objects are created by
default (the processor is a Celeron).

All of that is fine, and expected.

The sad thing is that the application ran fine on Windows 2000. So, I am
inclined to rule out any bugs in the way memory is claimed from the heap. Of
course, I understand that there is a difference between how the heap is
managed by the Windows libraries and the Watcom/QNX libraries. But I am
helpless in dealing with this. Therefore, I would really appreciate some
more insight into how I might be “writing before/after an allocated piece of
memory, damaging/destroying the information that the malloc library uses for
handling this stuff”.

I’m not positive of the current heap implementation, but I think you can
essentially think of it as a linked list of used blocks, and and a linked
list of free blocks.

So, if you look at what you’ve got laid out in memory, it might be
something like:

|memory handed out|size|address of next used chunk|

How do I mean damaged? Well some simple examples:

char *b;

b = malloc(strlen(some_other_string));
strcpy(b, some_other_string);

or

int c;
c = calloc( NUM_ITEMS, sizeof(int) );
for( i = 0; i <= NUM_ITEMS; i++ )
c _= 5
i + 10;

Neither of those bits of code would fail at the time they ran – but
they could damage the heap’s integrity and cause a later failure to
allocate memory, either in new, malloc, calloc, realloc, or maybe even
cause a problem in a free call._


Would allocating a big chunk of memory at once as
opposed to 35 steps of subsequent calls make a difference? The total amount
that is requested is below 17K anyway, not really a big amount of memory…

_Allocating a big chunk rather than multiple small chunks might change
the behaviour… if you’re doing something like I’ve shown, you might
now be corrupting your data instead of the heap maintenance data.

A different allocation algorithm, a different alignment choice, a
different way of heap representation – any of these could and would
change or mask the effects of bugs of the type I’ve described.

And, unfortunately, tracking something like this down in C or C++
code is messy and difficult.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions._

Thanks again for your insights David.

I found the problem and I fixed it. Following is a discussion of the
situation, for informational purposes only. However, I also have a question:
Does Watcom C++ 10.6 not support copy construction? The reason behind this
question will become apparent once you’ve read the following discussion.

In my code I am passing “String” objects from within some function scope to
another function down the path as arguments. MS Visual C++ 6.0 (remember, I
had mentioned that my code was running fine in Windows?) supports “copy
construction”, so that, passing the String object would cause the compiler
to create a new object with the exact same contents as the passed one,
inside the called function, and since the compiler uses the copy constructor
during this process, a new piece of memory gets allocated for the character
string embedded in the new String object. Now, the pointer inside the newly
created String object points to this new piece of memory.

However, if a copy constructor were not used, the C approach to argument
passing would be employed, in that, the original object’s contents would get
copied bit-by-bit. It is here where the problem occurs: Since the String
object has only a pointer as a member and not the original character string,
the pointer’s value will get copied into the new object, but this will point
to the character string of the original String object (the one that was
being passed into the function). So, when I return from this called
function, the local copy (created by bit-by-bit copying) will get destroyed
by a call to the class destructor. I do not know how this affects the piece
of memory in which the original character string is stored, one would have
to know the class implementation in the given language to be able to judge
on this. However, apparently that piece of memory is somehow affected
(returned to the heap?) as, in my code, the original String object is used
again in the caller function, and as such, it needs that piece of memory to
be intact. And, this is the point where the segment violation error occurs.

As a result, I am assuming that Watcom C++ 10.6 does not support copy
construction, which would have prevented this memory violation. The
description of the String class in the “Watcom C++ Class Library Reference”
shows an overloaded constructor in the form of

String::String(String const& str)

which is, normally, the syntax for the copy constructor, but copy
construction is not mentioned in the description.

Is it true that Watcom C++ 10.6 does not support copy construction (this is
only my guess)?

Anyhow, I have fixed the problem by stripping the String objects from the
code and using standard C-style character strings instead. Now the code
works.

Below is a representation of the structure of the affected portion of my
code. Only relevant staetements are represented:

class X
{
void* ptr;
String const memobj;
X(String s);
};

void func()
{
String strobj;

//do something with strobj
X* px_1= new X(strobj);

//do something with strobj
X* px_2= new X(strobj);

//do something with strobj
X* px_3= new X(strobj);

//do something with strobj
X* px_n= new X(strobj);
}

X::X(String s) : memobj(s) //memobj can be initialized only like this
{ //because it’s “const”.
ptr = calloc(…);
}


Thank you.

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:al5nd7$f0i$1@nntp.qnx.com