Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

top level defer is executed when it encounters import #10186

Closed
jiro4989 opened this issue Jan 4, 2019 · 5 comments
Closed

top level defer is executed when it encounters import #10186

jiro4989 opened this issue Jan 4, 2019 · 5 comments

Comments

@jiro4989
Copy link
Contributor

jiro4989 commented Jan 4, 2019

NG Example

import streams

var s = "test.dat".newFileStream fmWrite
defer: s.close
s.write '\x61'

# i think that here 'import' is problem.
import sequtils

for d in [1, 2, 3].mapIt($it):
  s.write d

Current Output

nim c -r defer.nim   
Traceback (most recent call last)
defer.nim(10)            defer
streams.nim(136)         write
streams.nim(112)         writeData
streams.nim(421)         fsWriteData
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Error: execution of an external program failed: '/tmp/defer '

OK Example

import streams
import sequtils

var s = "test.dat".newFileStream fmWrite
defer: s.close
s.write '\x61'

for d in [1, 2, 3].mapIt($it):
  s.write d

Output

Success executing.

Other close Example

var f = "test.txt".open fmReadWrite
defer: f.close

import sequtils

# Error is not occured.
# and "1" is not written.
f.write "1"
echo "end"

Output

$ nim c -r open.nim
end
$ cat test.txt | wc  
      0       0       0

Possible Solution

I think that executing 'import' then defer s.close is executed too.
This problem can be avoided, write imports at the beginning of the file.

Is it bad for compiler that writing the 'import' in the middle of file?

@jiro4989 jiro4989 changed the title import module after doing 'defer: close' then SIGSEGV fault import module and write file after doing 'defer: close' then SIGSEGV fault Jan 4, 2019
@krux02
Copy link
Contributor

krux02 commented Jan 4, 2019

I think the top level defer is causing the problem. For this use case you don't technically need the defer. When the process terminates the operating system will reliably close all remaining open file handles for you.

@nc-x
Copy link
Contributor

nc-x commented Jan 4, 2019

import streams

var s = "test.dat".newFileStream fmWrite
defer: s.close
s.write '\x61'

echo s.f.isNil            # false                 (first, export `f` in `FileStreamObj`)
import sequtils
echo s.f.isNil            # true           


for d in [1, 2, 3].mapIt($it):
  s.write d

defer is executing when it encounters import

@krux02 krux02 changed the title import module and write file after doing 'defer: close' then SIGSEGV fault top level defer is executing when it encounters import Jan 4, 2019
@krux02 krux02 changed the title top level defer is executing when it encounters import top level defer is executed when it encounters import Jan 4, 2019
@Araq
Copy link
Member

Araq commented Jan 4, 2019

Why is a toplevel defer statement even allowed? The compiler used to forbid that.

@krux02
Copy link
Contributor

krux02 commented Jan 4, 2019

I guess somebody "fixed" that limitation.

@nc-x
Copy link
Contributor

nc-x commented Jan 4, 2019

The code is still there

Nim/compiler/sem.nim

Lines 558 to 560 in be0a4d1

proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
if n.kind == nkDefer:
localError(c.config, n.info, "defer statement not supported at top level")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants