> > 2. I have been seeing some segmentation faults with some of our C
> > agents. The simpler ones that always return a constant string work,
> > but the ones which allocate and return a new C string often seg fault
> > right before sending the data on to the facilitator. This error is
> > cumulative and nondeterministic in that it usually doesn't happen
> > until after a few successful queries but it's pretty likely to happen
> > within 6 or 8 queries. Is there anything in particular about the
> > allocation of the string we pass off to OAA that we should know about
I am a little confused by your question, particularly by
the part that goes "always return a constant string" vs.
"allocate and return a new C string". But I'll tell you some
information about strings and allocation/deallocation and maybe
this will shed some light on the subject.
In OAA, there's lots of string manipulation functions (OAA 2.0
will just pass you a structure that you can traverse with pointers,
much nicer! No more double_quotes(), remove_quotes(),
undouble_quotes(), etc.) for the ICL. Most ICL parsing functions
return their result in a newly allocated string created using
malloc(Size) or strdup(Str), and then you can dispose of them using the
macro
OAA_FREE(result). OAA_FREE(ptr) just calls free(ptr), and then
sets the ptr to be NULL. This is because we've noticed that strange
things happen if you mistakenly free() the same pointer more than
once, so OAA_FREE() guarantees this doesn't happen. This could be
one source of your random error.
Example of good string use:
NthElt(args, 2, &result);
Use(result);
OAA_FREE(result);
One gotcha might come from the use of the Term() ICL parsing predicate,
which splits a comma separated list (e.g. "a, b, c") into a first
element and rest elements. Whereas ALMOST every ICL predicate returns
the results in new space which should be free'd, the last argument of
Term() returns a pointer back into the original string (first argument),
and this shouldn't be OAA_FREE'd. Term() was written this way for the
special purpose of iterating down lists, and really shouldn't be used
for any other reason. Here's the "right" way to iterate down a list of
elements:
char *p, *list, *elt;
// The right way to iterate lists
list = strdup("e1, e(2), e(e(3))"); // list is in newly allocated
space
p = list; // p will iterate through list, one elt at a time
while (p && *p) { // Keep iterating until p is empty string
Term(p, &elt, &p); // NEVER free p!!! It points into list's
space.
Use(elt);
OAA_FREE(elt);
}
OAA_FREE(list); // Free the original list space
By the way, this way to iterate is exponentially more efficient than
using something
like:
// REALLY INEFFICIENT!
for (i = 1; i++; i <= list_len(list)) {
NthElt(list, i, &elt);
Use(elt);
OAA_FREE(elt);
}
This is because predicates like list_len() and NthElt() themselves must
iterate over
the list using Term().
A last few words on the do_event() function in a C agent program.
do_event() should
return a boolean value indicating whether or not to use the answers
returned in the
last argument. This argument returns a newly allocated string (using
malloc() or strdup())
containing a Prolog list of results matching the incoming query, or
strdup("[]")
(the empty list "[]" represents failure). NEVER just set the result to
a "constant" string:
*answers = "[]"; // BAD
Here's a sample do_event function for the query "a(X)" which returns the
solution a(1):
int do_event(char *KS, char *func, char *args, char **answers) {
int numArgs = list_len(args);
int processed = TRUE;
char arg1 = NULL;
// for solvable: a(X)
if ((strcomp(func, "a") == 0) && (numArgs == 1)) {
NthElt(args, 1, &arg1);
if (is_var(arg1) || (strcomp(arg1, "1") == 0) {
*answers = malloc(BIG_ENOUGH); // Can use malloc to create
space for answer
sprintf(*answers, "[a(%d)]", 1); // Stores result into answer space
}
else
*answers = strdup("[]"); // Can use strdup to return result
}
else processed = FALSE; // not returning a result for this query
return processed;
}
Hope this helps. If you are really stuck, maybe you can send over the
OAA wrapper part
of your code and we can take a quick look to see if anything stands out
as unusual.
Regards,
Adam.
-- Adam J. Cheyer Artificial Intelligence Center Computer Scientist SRI International Email: cheyer@AI.SRI.COM Mail Stop: EJ217 WWW: http://www.ai.sri.com/~cheyer/ 333 Ravenswood Avenue Telephone: (650) 859-4119 Menlo Park, CA 94025-3493 Fax: (650) 859-3735 USA