I started learning LISP a few days back-
I use CLISP on Linux. I have a file called
`a.lsp' which contains the following code:
(setf p '(a))
(setf (cdr p) p)
(print p)
When I run it, the interpreter is eating up
all available memory. I understand that the
cdr pointer of the cons cell `p' is pointing
to itself - but what I don't understand is
why the interpreter is consuming memory.
Can anybody help?
Thanks and Regards,
Pramode C.E
-------------------
> Hello,
>
> I started learning LISP a few days back-
> I use CLISP on Linux. I have a file called
> `a.lsp' which contains the following code:
>
> (setf p '(a))
> (setf (cdr p) p)
> (print p)
>
> When I run it, the interpreter is eating up
> all available memory. I understand that the
> cdr pointer of the cons cell `p' is pointing
> to itself - but what I don't understand is
> why the interpreter is consuming memory.
> Can anybody help?
Yes.
The interpreter is consuming memory because it's trying to
print a circular list as if it's non-circular. This is a bad
thing, because it means that it will try and print it forever.
Set *PRINT-CIRCLE* to T to let the interpreter know that it's
likely to have to print circular data structures and you'll
get more graceful behaviour:
[1]> (setf *print-circle* t)
T
[2]> (setf p '(a))
(A)
[3]> (setf (cdr p) p)
#1=(A . #1#)
[4]> (print p)
#1=(A . #1#)
#1=(A . #1#)
Gabe Garza
--
; Matthew Danish <mda...@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
Unfortunately, this invokes undefined behavior, because you are modifying
a literal constant. This is a problem found in some other languages;
for example in C:
char *p = "a";
p[0] = 'b'; /* oops */
Instead, try:
(defvar *p* (list 'a))
(setf (cdr *p*) *p*)
>(print p)
>
>When I run it, the interpreter is eating up
>all available memory.
That's simply because it's trying to print the entire object,
which appears to be an infinitely long list.
Try doing this:
(setf *print-circle* t)
(defvar *p* (list 'a))
(setf (cdr *p*) *p*)
Now your Lisp system will recognize the circular reference
in the list and spit out the appropriate printed representation.
Best regards
AHz
> Kaz Kylheku wrote:
>
> > Unfortunately, this invokes undefined behavior, because you are modifying
> > a literal constant. This is a problem found in some other languages;
> > for example in C:
> >
> > char *p = "a";
> > p[0] = 'b'; /* oops */
>
> This is, in Lisp and in C, not a problem. [SNIP]
It is a problem in C:
,----
| davep@hagbard:~/temp$ cat foo.c
| int main( void )
| {
| char *p = "a";
|
| p[ 0 ] = 'b';
|
| return( 0 );
| }
|
| davep@hagbard:~/temp$ ./foo
| Segmentation fault (core dumped)
`----
--
Dave Pearson: | lbdb.el - LBDB interface.
http://www.davep.org/ | sawfish.el - Sawfish mode.
Emacs: | uptimes.el - Record emacs uptimes.
http://www.davep.org/emacs/ | quickurl.el - Recall lists of URLs.
The declaration of p creates a _pointer_, intialised to a
string that happens to be one character long, plus a null character
for termination. The string pointed to is commonly placed in a
read-only segment of memory (in Unix-speak, the "text" segment.)
--
Raymond Wiker Mail: Raymon...@fast.no
Senior Software Engineer Web: http://www.fast.no/
Fast Search & Transfer ASA Phone: +47 23 01 11 60
P.O. Box 1677 Vika Fax: +47 35 54 87 99
NO-0120 Oslo, NORWAY Mob: +47 48 01 11 60
Try FAST Search: http://alltheweb.com/
* Andy <a...@smi.de>:
The above code is attempting to modify a string literal. IIRC, the outcome
of such an attempt is "undefined". Dumping core is one possible, and
correct, outcome.
> Let me think about
> that.
<URL:http://www.eskimo.com/~scs/cclass/krnotes/sx8e.html> might be worth a
quick read before you do.
Making monkeys fly out of your butt is another possible, and correct,
outcome. Far less likely, though.
`Undefined' covers a lot of ground.
The point is that the declaration creates a *literal constant* object. Yes, it
is an array of two char; it occupies at least two bytes of storage which a
pointer can reference. But the behavior is not defined if you try to modify
that storage.
Lisp is the same way. Modify a quoted list and you are doing something
undefined and nonportable.
One implication of these rules is that language implementations are free to
place constant objects into read-only storage, such as virtual memory pages
that have read-only permissions. Or into actual ROM, like if you are generating
an image for an embedded system.
Some C compilers on Unix systems intersperse string literals among the
executable code. The code gets loaded into write-protected pages, protecting
the literals with it. This is the likely cause for the crash reproduced
by Dave Pearson's program above.
The second implication of these rules is that multiple occurences equivalent
constant objects can be folded into fewer instances, or perhaps into one
program-wide instance. Since the programmer has agreed to write the program
such that it does not modify the data, the program cannot be affected by this
folding, insofar as it does not rely on pointer comparisons in C, or EQ in
Lisp.
Constant data which is optimized into a compiled program's or function's image
can be a big efficiency improvement. Consider that '(1 2) does not have to cons
anything; whenever evaluated, it can just retrieve a pointer to the
same pre-computed list object.
It used to be allowable in C to write into string literals.
So gcc even has a backwards-compatibility flag for this:
snapdragon:~ > cat write-me.c
int main( void )
{
char *p = "a";
p[ 0 ] = 'b';
return( 0 );
}
snapdragon:~ > gcc -fwritable-strings -o write-me write-me.c
snapdragon:~ > ./write-me
snapdragon:~ > gcc -o write-me write-me.c
snapdragon:~ > ./write-me
Bus error (core dumped)
snapdragon:~ >
--
Fred Gilham gil...@csl.sri.com
Do remember you're there to fuddle him. From the way some of you
young fiends talk, anyone would suppose it was our job to teach!
-- The Screwtape Letters, C. S. Lewis
> > int main( void )
> > {
> > char *p = "a";
> >
> > p[ 0 ] = 'b';
> >
> > return( 0 );
> > }
>
>
> It used to be allowable in C to write into string literals.
No. The behavior was and still is undefined, so any compiler is free
to do whatever it likes. gcc changed its default behavior, that's all.
Regards,
--
Nils Goesche
"Don't ask for whom the <CTRL-G> tolls."
PGP key ID 0x42B32FC9