bugGNU Octave - Bugs: bug #33216, cell2struct does not allow to...

 
 

bug #33216: cell2struct does not allow to create an empty struct

Submitter:  None
Submitted:  Tue 03 May 2011 01:43:24 PM UTC
   
 
Category:  None Severity:  3 - Normal
Priority:  7 - High Item Group:  Segfault, Bus Error, etc.
Status:  Fixed Assigned to:  jordigh
Originator Name:  Jochen Weber Originator Email:  -email is unavailable-
Open/Closed:  * Closed Release:  * 3.6.1
Operating System:  * Any Fixed Release:  None
Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Fri 11 May 2012 04:39:34 PM UTC, comment #7: 

I checked in the following change.

http://hg.savannah.gnu.org/hgweb/octave/rev/edf9ca8a92a8

This problem will be fixed in the upcoming 3.6.2 release.

John W. Eaton <jwe>
Group administrator
Wed 09 May 2012 06:24:33 AM UTC, comment #6: 

Happy belated birthday, bug #33216

This is a very, very corner case. I'd be surprised if anyone other than Jochen Weber has ever run into this.

The issue is that dim_vector::redim will pad with 0 instead of 1 if all of the dimensions of the dim_vector are 0. When you do cell(0,0,1), this in fact is equivalent to cell(0,0) since singleton dimensions are chopped, so it's a cell with all zero dimension vector. The rest of the cell2struct code assumes redim will pad with ones, but in this case it won't. When this assumption breaks in the assertion, you get a SIGABRT or whatever the OS in question does with failed assertions.

I'm working on a fix.

Jordi GutiƩrrez Hermoso <jordigh>
Group Member
Thu 05 May 2011 01:24:33 PM UTC, comment #5: 

Hello John and Jaroslav,

From what I can tell, the problem might be that, according to Matlab's standard (which is, as far as I can see, also implemented in Octave), any non-specified "size" (number of indices in any given dimension) beyond the second dimension is automatically considered to be 1 and thus not stored.

Take for example (from my Mac OSX Octave v3.4.0):


octave-3.4.0:1> size([], 3)
ans =  1
octave-3.4.0:2> size(zeros(0,0), 3)
ans =  1
octave-3.4.0:3> size(cell(0,0,1), 3)
ans =  1
octave-3.4.0:4> ndims(cell(0,0,1))
ans =  2


It would thus seem necessary that, in case a dimension has to be checked for size, this might best be done by an inline function:


inline SIZE_TYPE size_at_dim(const SIZE_TYPE* sizes, int ndims, int at_dim)
{
    return (at_dim >= ndims) ? (SIZE_TYPE) 1 : sizes[at_dim];
}


PS: I'm an awful C coder, but you'll get the idea...

Does this help?
/jochen

Jochen Weber <jweber>
Thu 05 May 2011 04:00:16 AM UTC, comment #4: 

Jaroslav, I'm adding you to the CC list for this bug because you added the code that contains the assertion that is failing with the test case


cell2struct(cell(0,0,1), {'f1'}, 3)


Will you please take a look at this problem?

The changeset that added the assertion is

http://hg.savannah.gnu.org/hgweb/octave/rev/bee1b1a2e29a

I'm not sure what is supposed to happen here.  Are the dimensions being set incorrectly?  Trailing singletons not handled properly?  Or should there just be a special case for empty arrays?

John W. Eaton <jwe>
Group administrator
Wed 04 May 2011 04:55:23 AM UTC, comment #3: 

Confirmed on versions 3.4.0 and on the development branch.  I've changed the group of the bug to Crash since this causes a segfault and I've also bumped up the priority.

Rik <rik5>
Group administrator
Wed 04 May 2011 02:27:37 AM UTC, comment #2: 

It seems that I mistook the error message I got in case I use only one field for a general case.

On my Mac, I get for Octave version 3.4.0:


octave-3.4.0:1> s = cell2struct(cell(0,0,1), {'f1'}, 3)
Assertion failed: (ext == rdv(dim)), function Fcell2struct, file ov-struct.cc, line 2079.
panic: Abort trap -- stopping myself...
attempting to save variables to `octave-core'...
save to `octave-core' complete
/Applications/Octave.app/Contents/Resources/bin/octave: line 68:   310 Abort trap              OCTAVE_HOME="${OCTAVE_HOME}" PATH="${PATH}" DYLD_LIBRARY_PATH="${DYLD_LIBRARY_PATH}" CC="${CC}" CXX="${CXX}" CFLAGS="${CFLAGS}" CPPFLAGS="${CPPFLAGS}" CXXFLAGS="${CXXFLAGS}" FFLAGS="${FFLAGS}" LDFLAGS="${LDFLAGS}" DL_LDFLAGS="${DL_LDFLAGS}" SED="$SED" MAGICK_HOME="${ROOT}" FONTCONFIG_PATH="${ROOT}/etc/fonts" "${ROOT}/bin/octave-3.4.0" "$@"

[Process completed]


And under Octave 3.2.3 I get


octave-3.2.3:1> s = cell2struct(cell(0,0,1), {'f1'}, 3)
error: cell2struct: DIM out of range


While a struct with only one field might seem stupid to use, I still think it should not give an error or crash...

/jochen

Jochen Weber <jweber>
Wed 04 May 2011 01:51:44 AM UTC, comment #1: 

Could you be more specific about what you expect the output for init_struct to look like?  When running your code I get


init_struct = cell2struct(cell(0, 0, 2), {'field1', 'field2'}, 3)
init_struct =

  0x0 struct array containing the fields:

    field1
    field2


which seems correct.

Rik <rik5>
Group administrator
Tue 03 May 2011 01:43:24 PM UTC, original submission:  

In many of my codefiles I'm currently using the following syntax to produce a 0x0 struct with a fix set of fields (against which I later run checks) but no content (no memory required for pointers, etc.):


init_struct = cell2struct(cell(0, 0, 2), {'field1', 'field2'}, 3);


In Matlab this works as expected:

 - taking the dims of the first input that are not the fieldnames dim (0 and 0) as output dims
 - and then creating the output struct with the requested fields

As a workaround I'm currently using a function to initialize structs:


function s = emptystruct(fields, dim)

% argument check
if nargin < 1 || ...
   ~iscell(fields)
    error( ...
        'neuroelf:BadArgument', ...
        'Bad or missing argument.' ...
    );
end
if nargin < 2 || ...
   ~isa(dim, 'double') || ...
    numel(dim) < 2 || ...
    numel(dim) ~= size(dim, 2) || ...
    any(isinf(dim) | isnan(dim) | dim < 0 | dim >= 2^31 | dim ~= fix(dim))
    dim = [0, 0];
end
dim0 = (prod(dim) == 0);

% create struct
if numel(fields) == 0;
    s = struct;
else
    s = cell2struct(cell(numel(fields), 1), fields(:)', 1);
end
if dim0
    s(:) = [];
    if any(dim > 0)
        s = reshape(s, dim);
    end
else
    s = repmat(s, dim);
end


Anonymous

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by jordigh (Posted a comment)
  • -email is unavailable- added by jwe (Posted a comment)
  • -email is unavailable- added by jwe
  • -email is unavailable- added by jweber (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by None (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 11 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2012-05-11 jwe StatusIn Progress Fixed
        Open/ClosedOpen Closed
    2012-05-09 jordigh StatusConfirmed In Progress
        Assigned toNone jordigh
        Release3.4.0 3.6.1
        Operating SystemMac OS Any
    2011-05-05 jwe Carbon-Copy- Added -email is unavailable-
    2011-05-04 rik5 Priority5 - Normal 7 - High
        Item GroupPerformance Segfault, Bus Error, etc.
        StatusNeed Info Confirmed
    2011-05-04 rik5 StatusNone Need Info

    Back to the top

    Powered by Savane 3.13-3230.
    Corresponding source code