Skip to content

PyArray_DescrConverter inconsistency with empty arrays in records (Trac #1600) #2196

Closed

Description

@numpy-gitbot

Original ticket http://projects.scipy.org/numpy/ticket/1600 on 2010-09-02 by trac user steveb, assigned to unknown.

When a record type is defined using a dictionary, dtype doesn't allow zero length arrays.

np.dtype([('val1', np.float32, (0,))]) # OK
np.dtype({'names': ['val1'], 'formats':[(np.float32, (0,))]}) # Throws TypeError

It isn't clear to me why they shouldn't be allowed in this case.

Activity

  1. numpy-gitbot commented on Oct 19, 2012

    @numpy-gitbot
    Author

    Attachment added by trac user steveb on 2010-09-02: create_from_dict_elsize.patch

  2. modified the milestone: on Feb 20, 2014
  3. charris commented on Feb 20, 2014

    @charris
    Member

    Not sure about the patch, it hasn't been applied.

  4. ahaldane commented on Aug 1, 2015

    @ahaldane
    Member

    Disallowing size-0 fields in structured arrays is intentional, the patch is the wrong solution. Size-0 fields cause segfaults, as seen in #473, #4955, #2585, #1901.

    The problem here is not that the dict form of specification disallows size-0 fields, but rather that the list form of specification should not allow them but does!

    Now, probably the ideal solution would be to get rid of the segfaults and allow 0-sized fields. However that seems tricky. Consider how this problem was solved for unstructured types: You can create size-0 types, but if you ever try to create an array with one it gets automatically modified to be size-1. We can't do that with structured array fields since it would change all subsequent field offsets.

    >>> d = dtype('S')
    >>> d, d.itemsize
    (dtype('S'), 0)
    >>> a = np.zeros(2, dtype=d)
    >>> a.dtype, a.dtype.itemsize
    (dtype('S1'), 1)
    
  5. njsmith commented on Aug 1, 2015

    @njsmith
    Member

    I guess a valid alternative solution would be to go around and fix all the
    places that crash given size zero dtypes.
    On Aug 1, 2015 7:51 AM, "ahaldane" [email protected] wrote:

    Disallowing size-0 fields in structured arrays is intentional, the patch
    is the wrong solution. Size-0 fields cause segfaults, as seen in #473
    #473, #4955
    #4955, #2585
    #2585, #1901
    #1901.

    The problem here is not that the dict form of specification disallows
    size-0 fields, but rather that the list form of specification should not
    allow them but does!

    Now, probably the ideal solution would be to get rid of the segfaults and
    allow 0-sized fields. However that seems tricky. Consider how this problem
    was solved for unstructured types: You can create size-0 types, but if you
    ever try to create an array with one it gets automatically modified to be
    size-1. We can't do that with structured array fields since it would change
    all subsequent field offsets.

    d = dtype('S')
    d, d.itemsize
    (dtype('S'), 0)
    a = np.zeros(2, dtype=d)
    a.dtype, a.dtype.itemsize
    (dtype('S1'), 1)

    —
    Reply to this email directly or view it on GitHub
    #2196 (comment).

  6. embray commented on Oct 7, 2015

    @embray
    Contributor

    I was under the impression that zero-size dtypes are supported now. They used to just not work at all (and indeed lead to segfaults). But I do have code that relies on this, and at least as of Numpy 1.6 that code has been working (previously I had to rely on gnarly workarounds for zero-width fields).

    Maybe the fact that it happens to be working for my case is a happy accident though.

    Nonetheless the point stands that it's possible to create a record dtype with zero-width fields using the list-based constructor, but not with the dict-based constructor. That inconsistency is a bug no matter what.

    As for @ahaldane's example above, I think it's more of a special case. In fact in other cases it is disallowed:

    >>> np.zeros(2, dtype=np.dtype('|V0'))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: Empty data-type

    But in the case of empty strings it happens to work:

    >>> np.zeros(2, dtype=np.dtype('S'))
    array([b'', b''], 
          dtype='|S1')

    But that only works because as a special case for strings it converts an 'S0' to 'S1'. It's not using a zero-width dtype anymore:

    >>> np.zeros(2, dtype=np.dtype('S')).itemsize
    1

    So I think that's beside the point.

    Where I've used this is in cases (which I agree are completely absurd, but believe me when I say there's a use-case):

    >>> np.dtype(('f8', (0,)))
    dtype(('<f8', (0,)))

    This is an odd-looking case, but it actually ends up being treated as equivalent to '|V0', just with dtype('float64') as its .base instead of dtype('V'). This works in most cases though, and I think cases where it doesn't work should be fixed, instead of saying it's illegal (which currently it isn't as far as construction is concerned...)

  7. njsmith commented on Oct 7, 2015

    @njsmith
    Member

    @embray: I don't see any reason why we can't make zero-width fields inside record arrays legal and supported, but it's quite possible that you're the only one who cares enough to put the effort into making them work :-).

  8. embray commented on Oct 7, 2015

    @embray
    Contributor

    Going through the above issues one by one now--will update this comment as I go.

  9. ahaldane commented on Oct 7, 2015

    @ahaldane
    Member

    I think above I was worried about what would be returned if you subscripted a 0-sized array (to get an element). But I think I was just confused - you'd get en empty string, or an empty buffer, or an empty array. So I agree with @njsmith.

    Also back then I hadn't figured out how to use gdb to diagnose segfaults, so tracking down the ones I linked above was daunting. Seems very doable now!

  10. embray commented on Oct 7, 2015

    @embray
    Contributor

    but it's quite possible that you're the only one who cares enough to put the effort into making them work

    Maybe so... though at least other people have reported these issues too (that's how I found this one--went looking to see if it was reported before doing so myself). I actually ran into this a long time ago but got too distracted to report it at the time.

    I'd happily take a look at fixing this. Almost all of those issues are probably symptoms of the same one or two bugs.

  11. embray commented on Oct 7, 2015

    @embray
    Contributor

    And I'm an adept gdb user :), so since I can reproduce the crash in #473 it shouldn't be hard to track down. I'll have a look...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions