Odd error message on open()-ing scalar ref

Discussion in 'Perl Misc' started by Hartmut Camphausen, Jul 13, 2008.

  1. Hi all,

    Consider this snippet:

    #!perl.exe -w
    use strict;

    my $f = 'abc';
    my $fref = \$f;

    my $fh;
    warn "(0) $!" if $!;
    open ($fh, '<', $fref) || die $!
    warn "(1) $!" if $!;

    print "\n", <$fh>;
    seek ($fh, 1, 0) || die $!;
    print "\n", <$fh>;

    It produces this output:

    (1) Bad file descriptor at E:\[Public]\cgi-bin\lib\Text\testmisc.pl
    line 10.

    Tool completed successfully

    Any idea, why open() generates an error ($! set) without failing?
    open() dies correctly if I dereference $fref via $$fref (No such
    I'm running Perl v5.8.8.

    Hartmut Camphausen, Jul 13, 2008
    1. Advertisements

  2. Hartmut Camphausen

    xhoster Guest

    Open did not fail. Therefore, the value of $! is meaningless. Meaningless
    can be anything, including the value you see above.
    Setting $! is *not* generating an error[1]. The way that open indicates an
    error is by returning a false value (or conceivably by dying). It did not
    do that.

    [1] And "open" is not setting it anyways, at least not directly. Most
    likely your use of open is triggering the loading of PerlIO::scalar, and it
    is the loading of PerlIO::scalar that is setting $!, but in an innocuous
    manner. On my system, if I preload that module by "use PerlIO::scalar",
    and then reset $! to 0, then do your open, after the open $! remains 0.
    But that doesn't really matter, as by inspecting $! when an error has not
    occurred you are living in sin.


    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    xhoster, Jul 13, 2008
    1. Advertisements

  3. The open() entry in perlfunc contains part of the answer:

    Since v5.8.0, [...] you can open file handles to "in memory"
    files held in Perl scalars via:

    open($fh, '>', \$variable) || ..

    This is what you're doing except that you're opening the handle for
    reading instead of writing. The open() isn't returning false because it
    isn't failing. This can be seen in the output of your print() statements.

    The rest of the answer is in the entry for $! in perlvar:

    if a system or library call fails, it sets this variable.
    This means that the value of $! is meaningful only *immediately*
    after a failure:

    Since there was no failure, the value of $! isn't meaningful.

    Michael Carman, Jul 13, 2008
  4. Hi xho, Michael,

    many thanks for your quick and enlightening responses.

    @ xho:
    Ah yes! I kind of thought that function failing and setting $! belongs
    together - and /vice versa/: No fail, no $!.

    But as Michael quoted:
    I should better have remembered that, just read it a short while ago :p

    Thanks again + mfg,
    Hartmut Camphausen, Jul 13, 2008
  5. You have a syntax error here, you forgot the semicolon after $!. Please
    post correct code on the newsgroup ;-)

    Leon Timmermans
    Leon Timmermans, Jul 14, 2008
  6. Hi Leo,
    Oh yes. You are right. I should have taken it with me, just like the
    other one.

    Thanks for the hint anyway :)

    mfg, Hartmut
    Hartmut Camphausen, Jul 14, 2008
  7. That might have been more obvious had the OP not decided to format Perl
    as if it is assembly language.

    I realize beauty is in the eye of the beholder but I would urge the OP
    to read

    perldoc perlstyle

    to ensure that his code is accessible to as many people as possible
    (especially when requesting help in a public forum).
    That would help.


    A. Sinan Unur <>
    (remove .invalid and reverse each component for email address)

    comp.lang.perl.misc guidelines on the WWW:
    A. Sinan Unur, Jul 14, 2008
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.