4 |
see-also-dir: 1001.stuff |
see-also-dir: 1001.stuff |
5 |
test-case: segf-v1.scm |
test-case: segf-v1.scm |
6 |
test-case: segf-v2.scm (ignore for now) |
test-case: segf-v2.scm (ignore for now) |
7 |
|
fixed: Neil Jerram, 2002-07-13, guile-core, HEAD |
8 |
|
|
9 |
M Johnson sez: |
M Johnson sez: |
10 |
> I'm assuming that when (backtrace) seg-faults that that is a bug, no matter how screwed up my cod may be. |
> I'm assuming that when (backtrace) seg-faults that that is a bug, no matter how screwed up my cod may be. |
114 |
|
|
115 |
ttn sez: |
ttn sez: |
116 |
> second posted test case is sadistic; ignoring for now. |
> second posted test case is sadistic; ignoring for now. |
117 |
|
|
118 |
|
|
119 |
|
Fix by Neil Jerram... |
120 |
|
|
121 |
|
Patch |
122 |
|
|
123 |
|
--- /home/neil/Guile/1.6/guile-core/libguile/eval.c.old Thu May 2 12:45:56 2002 |
124 |
|
+++ /home/neil/Guile/1.6/guile-core/libguile/eval.c Thu May 2 12:46:21 2002 |
125 |
|
@@ -1417,7 +1417,9 @@ |
126 |
|
ls = scm_cons (scm_sym_define, |
127 |
|
z = scm_cons (n = SCM_CAR (x), SCM_UNSPECIFIED)); |
128 |
|
if (SCM_NNULLP (env)) |
129 |
|
- SCM_SETCAR (SCM_CAR (env), scm_cons (n, SCM_CAR (SCM_CAR (env)))); |
130 |
|
+ env = scm_cons (scm_cons (scm_cons (n, SCM_CAAR (env)), |
131 |
|
+ SCM_CDAR (env)), |
132 |
|
+ SCM_CDR (env)); |
133 |
|
break; |
134 |
|
} |
135 |
|
case SCM_BIT8(SCM_MAKISYM (0)): |
136 |
|
|
137 |
|
Diagnosis |
138 |
|
|
139 |
|
If scm_unmemocopy is called (e.g. from scm_backtrace) to unmemoize an |
140 |
|
expression that has an internal define (i.e. SCM_IM_DEFINE) near the |
141 |
|
top level of the expression, the code in unmemocopy can modify the |
142 |
|
expression passed in. The modification is such that an extra copy of |
143 |
|
the symbol being defined is added on every call, thus: |
144 |
|
|
145 |
|
(((args) 4) ...) |
146 |
|
(((xxx args) 4) ...) |
147 |
|
(((xxx xxx args) 4) ...) |
148 |
|
|
149 |
|
and so on, and this modification eventually causes some other code |
150 |
|
that looks at the environment to SEGV. |
151 |
|
|
152 |
|
The copy in scm_unmemocopy, which looks as though it might be intended |
153 |
|
to fix this problem, doesn't work because it only copies the |
154 |
|
environment's top-level pair, and it is the car of the car of the |
155 |
|
environment that gets modified as just described. |
156 |
|
|
157 |
|
Fix notes |
158 |
|
|
159 |
|
Basically, avoid modifying the environment in hand by making new list |
160 |
|
structure instead. This is similar to almost all the other cases in |
161 |
|
unmemocopy, which use EXTEND_ENV. Fix isn't very elegant, though; |
162 |
|
is there a nicer way of doing this? |
163 |
|
|
164 |
|
Checks |
165 |
|
|
166 |
|
1. make check passes. |
167 |
|
|
168 |
|
2. Rerun of problem scenarios: |
169 |
|
|
170 |
|
guile> (define (fnc args) (local-eval '(define xxx 3) (the-environment))) |
171 |
|
guile> (fnc 4) |
172 |
|
standard input:1:33: In expression (define xxx 3): |
173 |
|
standard input:1:33: Bad define placement |
174 |
|
ABORT: (misc-error) |
175 |
|
|
176 |
|
Type "(backtrace)" to get more information or "(debug)" to enter the debugger. |
177 |
|
guile> (debug) |
178 |
|
This is the Guile debugger; type "help" for help. |
179 |
|
There are 3 frames on the stack. |
180 |
|
|
181 |
|
Frame 2 at standard input:1:33 |
182 |
|
(define xxx 3) |
183 |
|
debug> eval (the-environment) |
184 |
|
;value: (((args) 4) #<eval-closure 40262bd0>) |
185 |
|
debug> ba |
186 |
|
In standard input: |
187 |
|
2: 0* [fnc 4] |
188 |
|
1: 1 [local-eval (define xxx 3) (((args) 4) #<eval-closure 40262bd0>)] |
189 |
|
1: 2* (define xxx 3) |
190 |
|
debug> eval (the-environment) |
191 |
|
;value: (((args) 4) #<eval-closure 40262bd0>) |
192 |
|
guile> |
193 |
|
|
194 |
|
guile> (load "/home/neil/segf.scm") |
195 |
|
guile> (assignments (command-line)) |
196 |
|
<unnamed port>: In expression (define a (option-ref options b ...)): |
197 |
|
<unnamed port>: Bad define placement |
198 |
|
ABORT: (misc-error) |
199 |
|
|
200 |
|
Type "(backtrace)" to get more information or "(debug)" to enter the debugger. |
201 |
|
guile> (backtrace ) |
202 |
|
|
203 |
|
Backtrace: |
204 |
|
In standard input: |
205 |
|
2: 0* [assignments ("/usr/local/bin/guile")] |
206 |
|
In /home/neil/segf.scm: |
207 |
|
2: 1 (let ((env #)) (for-each (lambda # #) (quote #))) |
208 |
|
3: 2 [for-each #<procedure #f (triplet)> ((a b c) (d e f))] |
209 |
|
In unknown file: |
210 |
|
?: 3* [#<procedure #f (triplet)> (a b c)] |
211 |
|
In /home/neil/segf.scm: |
212 |
|
5: 4* (let ((x #) (y #) (z #)) (local-eval (quasiquote #) env)) |
213 |
|
8: 5 [local-eval (define a #) (# #)] |
214 |
|
In unknown file: |
215 |
|
?: 6* (define a (option-ref options b c)) |
216 |
|
|
217 |
|
Type "(debug-enable 'backtrace)" if you would like a backtrace |
218 |
|
automatically if an error occurs in the future. |
219 |
|
guile> |