Techniques for Avoiding Trouble
from the official adesk ads documentation
Passing Pointers Instead of Data Structures
One frequent problem of programming with ADS is due to the large number of
library functions that pass their results by reference. In all such cases,
the application must define an argument of the appropriate size and type. It is tempting to define
the argument as a pointer
to the correct type , b ut this causes the library function to return garbage data, and can cause
other data in memory to be corrupted .
T he mistake is illustrated by
ads_getangle() in the following function fragment: int thing()
{
ads_real *result; /* Only allocates space for pointer */
ads_point pt;
pt[X] = .;
pt[Y] = .;
pt[Z] = .;
if (ads_getangle(pt, "Enter desired angle: ", result)
!= RTNORM)
return BAD;
.
.
.
}
The result argument should be declared as
ads_real , as shown
here
in the corrected version . int thing()
{
ads_real result; /* Allocates space for real number */
ads_point pt;
pt[X] = .;
pt[Y] = .;
pt[Z] = .;
if (ads_getangle(pt, "Enter desired angle: ", &result) != RTNORM)
return BAD;
.
.
.
}
As the preceding e xample shows, the mistake can be hard to catch because the error is mainly
in the argument declaration and not in the function call as such ; t he giveaway is the absence of the address operator
& . The problem becomes harder to see when the result argument is a string or
an
array (such as
ads_point ), because string and array names are already pointers a nd do not require the
& operator. The mistake is illustrated here by
ads_rtos() . char *rlstr; /* Allocates only the pointer */
ads_real dist;
dist = ads_rtos(dist, rlstr); /* WRONG!! */
This does not provide enough space for the result buffer. A correct way to
declare the buffer and call ads_rtos() is shown by the next excerpt . char rlstr[13]; /* Allocates room for the string */
ads_real dist;
dist = ads_rtos(dist, rlstr);
If the application seems to be working with garbled data, check the declarations
of variables used as result arguments in calls to the ADS library. Failing to Free Selection Sets
One of the most insidious errors that a n ADS application can make is failing to release the selection sets it creates
with calls to
ads_ssget() and
ads_ssadd() ; e ach call that creates a new selection set must be matched by a call to
ads_ssfree() . AutoCAD permits only a limited number of selection sets to be open at a
given time (it does n't m atter whether
or not
the selection set contains entities ) . If you forget to
use
ads_ssfree() to free a selection set, you use u p one of this limited number of sets. Sooner or later, the application will
run out of selection sets and
ads_ssget() operations will fail without apparent reason. Even worse, the
ads_ssget() call that fails may be unrelated to the command that is losing selection sets , and
may in fact b e in a different application. If your application runs for a while and then
fails, but starts to work again after you restart AutoCAD,
f ailure to release selection sets with
ads_ssfree() is
most likely t he cause. Carefully read code that handles selection sets , and make sure that every selection set obtained is eventually released by
a call to
ads_ssfree() . Pay special attention to error-handling code . Wh en
you write c ode that returns under error conditions, it is easy to forget to release
all selection sets that are open.
If ads_ssget() reports an error (that is, if it does not return
RTNORM ), it does not create a new selection set, so you don't have to release the
specified selection set name. The same applies to
ads_ssadd() when it is called with null pointers to create a new selection set.
Failing to Use Long Integers as Selection S et Indexes
Because AutoCAD selection sets can contain more than 65,535 entities, the
selection s et indexes used in the
ads_sslength() and
ads_ssname() functions are of the type
long .
Because s ome implementations of C treat the
int type as 16 bits, equivalent to a
short , it is essential that you declare the variables used with these functions as
long . Special caution is required when you
are d eveloping an ADS application on a system (including many UNIX systems) on
which the
int and
long types are identical . If you inadvertently declare a selection s et index as an
int and you later port it to a
short integer system (such as OS/2), y our application will fail in obscure ways .
For the same reasons, if you use a constant in a call to ads_ssname() , pass it as a
long value by appending an
L to the value ( as in
112L ). (Standard C compilers correctly promote 16-bit integers to
long s, but this can cause problems if you recompile your application using an
older version of C.) Failing to Release Result Buffers
Several ADS functions dynamically allocate storage for results they return.
Your application should release these buffers with calls to ads_relrb() or
free() , as appropriate. A program that fails to release result buffers will appear
to be working properly but will eventually run out of memory, causing symptoms
that
may a ppear long after the storage was lost. Also, the performance of AutoCAD can
be affected even after the application has been unloaded.
Pay particular attention to code that uses result buffers, and verify that
all paths following the allocation of a buffer end in its release. Also,
note that ads_getvar() , which is passed a static result buffer, dynamically allocates a buffer
to return results of type
RTSTR ; t his string must be released with a call to
free() .
Opening Files in Shared Mode
When AutoCAD and AutoLISP access files, they do so in an exclusive mode to
prevent other programs from tampering with a file's contents while it is
being read or written. Your ADS applications should do the same. They should
never open files in a shared mode for either reading or writing. This is
especially important when your application is accessing files that belong
to AutoCAD. If you open an AutoCAD file using a shared mode, AutoCAD cannot
access it and may h ang. Even if the file is not an AutoCAD file, using a shared mode can lead
to conflicts with other applications that access the same file. Problems
that arise from this situation can be difficult to trace, especially in a
network environment.
The details of how to ensure that
your application has exclusive access to an open file vary from platform
to platform. Your system's documentation should explain how to do
this. Also , check the platform-specific on-line documents shipped with AutoCAD to see
if they contain advice about how to open and close files.