> Dennis:
> 
> You shot yourself in the foot.

I am not so sure. 

There is a fault somewhere in Solaris 10 I think. I am guessing and am hunting 
for proof. 
I have a wee mystery as to why this works flawlessly on every linux I tried 
thus far as well
as on Solaris 8 i386 and also on Solaris 10 when I compile as a 32-bit generic 
binary.

Please see below because I am having a hard time finding the data. 

>      int *comb;
> ...
>      comb = ( int * ) calloc( (size_t) k, sizeof(int) );
>      for ( i = 0; i < k; ++i)
>          *( comb + i * sizeof(int) ) = i;
> 
> 'comb' is a pointer to an int.

 *nod*

> As such, 'comb + n' is really '(caddr_t)comb + n * sizeof (int))'

Really?

Let's check that with dbx. 

I was thinking the same way as you and made the mistake of allocating too much 
memory in 
line 95.  The calloc was at line 95 in main thus : 

    comb = ( int * ) calloc( (size_t) k, sizeof(int) );

So I have k * sizeof(int) bytes of memory made available to me.  Too much.  
There only needs to be ( k-1 ) slots of sizeof(int), not k.  

Thus, in fact try this yourself and show me the error please :  

$ mdigest -a sha1 combinations.c
b5ca76095a364ab67bd86863b6f94e006909aae7  combinations.c

$ c99 $CFLAGS -o combinations combinations.c

$ dbx combinations
Reading combinations
Reading ld.so.1
Reading libc.so.1
(dbx) stop at 95                                                             
(2) stop at "combinations.c":95
(dbx) run 30 22 > /dev/null
Running: combinations 30 22 > /dev/null
(process id 3507)
stopped in main at line 95 in file "combinations.c"
   95       comb = ( int * ) calloc( (size_t) k, sizeof(int) );
(dbx) print comb
dbx: warning: cannot recreate macro information for combinations.c -- 
unrecognized compiler : /opt/solarisstudio12.3/prod/bin/c99
comb = (nil)
(dbx) step      
Reading libc_psr.so.1
stopped in main at line 97 in file "combinations.c"
   97       for ( i = 0; i < k; ++i)
(dbx) print comb
comb = 0x100101500

        So comb points to memory at 0x100101500h and I expect k * sizeof(int) 
more bytes. 

(dbx) print *comb
*comb = 0
(dbx) print sizeof(int)
sizeof(int ) = 4
(dbx) print k         
k = 22
(dbx) print ( comb + 22 * 4 )
comb+22*4 = 0x100101660

         That address looks correct to me. 

(dbx) print *( comb + 22 * 4 )
*(comb+22*4) = 0

        We see calloc did its job of providing zeroed out memory up to there no 
problem. 

(dbx) stop at 101             
(3) stop at "combinations.c":101
(dbx) cont      
stopped in main at line 101 in file "combinations.c"
  101       printc( comb, k );
(dbx) print *( comb + 22 * 4 )
*(comb+22*4) = 0

          like I said above .. too much memory. I never touched addr (comb + k 
* sizeof(int) ).

(dbx) print *( comb + 21 * 4 )
*(comb+21*4) = 21

          looks perfect to me, furthermore : 

(dbx) print *( comb + 21 * 4 )
*(comb+21*4) = 21
(dbx) print *( comb + 16 * 4 )
*(comb+16*4) = 16
(dbx) print *( comb + 8 * 4 ) 
*(comb+8*4) = 8
(dbx) print *( comb + 4 * 4 ) 
*(comb+4*4) = 4
(dbx) print *( comb + 2 * 4 ) 
*(comb+2*4) = 2
(dbx) print *( comb + 1 * 4 ) 
*(comb+1*4) = 1
(dbx) print *( comb )        
*comb = 0
(dbx) cont           
signal SEGV (no mapping at the fault address) in _malloc_unlocked at 
0xffffffff7ef63624
0xffffffff7ef63624: _malloc_unlocked+0x023c:    ldx      [%g5 + 16], %o1
Current function is printc
   28       printf("{ ");
(dbx) regs
current frame:  [6]
g0-g1    0x0000000000000000 0x0000000600003f70
g2-g3    0x0000000000000000 0x0000000000000000
g4-g5    0x0000000600003f70 0x00000007001054d0
g6-g7    0x0000000000000000 0xffffffff7f100200
o0-o1    0x0000000100000fe8 0x0000000000000000
o2-o3    0x0000000000000000 0xffffffff7f1496dc
o4-o5    0xffffffff7f13e000 0x0000000000000002
o6-o7    0xffffffff7fffec61 0x0000000100000b0c
l0-l1    0x0000000100000fe8 0x0000000000000000
l2-l3    0x0000000000000000 0x0000000000000000
l4-l5    0x0000000000000000 0x0000000000000000
l6-l7    0x0000000000000000 0x00000001001010a8
i0-i1    0x0000000100101500 0x0000000000000016
i2-i3    0x0000000000000000 0xfffffffffffffff8
i4-i5    0x0000000000000000 0x0000000100101558
i6-i7    0xffffffff7fffed31 0x0000000100000f28
y        0x0000000000000000
ccr      0x0000000000000099
pc       0x0000000100000b0c:printc+0x2c    call     printf [PLT]        ! 
0x1001011e0
npc      0xffffffff7ef63628:_malloc_unlocked+0x240    and      %o1, -3, %o0
(dbx) 
(dbx) quit                    
$ 

Same code runs fine on Linux compiled with GCC 4.7.2.  Same code runs fine on 
Solaris 8.
Really .. I don't see where I end up looking at *(comb + some_offset) outside 
of the allocated area. 

Just for giggles here is the same situation on a Solaris 8 i386 boxen : 

titan-i386-SunOS5.8 $ dbx combinations
Reading combinations
Reading ld.so.1
Reading libc.so.1
Reading libdl.so.1
(dbx) stop at 95                                                             
(2) stop at "combinations.c":95
(dbx) run 30 22 > /dev/null
Running: combinations 30 22 > /dev/null 
(process id 805)
stopped in main at line 95 in file "combinations.c"
   95       comb = ( int * ) calloc( (size_t) k, sizeof(int) );
(dbx) print comb          
comb = 0x8047a4c
(dbx) step      
stopped in main at line 97 in file "combinations.c"
   97       for ( i = 0; i < k; ++i)
(dbx) print comb
comb = 0x8060e18
(dbx) print *comb
*comb = 0
(dbx) print sizeof(int)
sizeof(int ) = 4
(dbx) print k         
k = 22
(dbx) print ( comb + 22 * 4 )
comb+22*4 = 0x8060f78
(dbx) print *( comb + 22 * 4 )
*(comb+22*4) = 1376259
(dbx) stop at 101             
(3) stop at "combinations.c":101
(dbx) cont      
stopped in main at line 101 in file "combinations.c"
  101       printc( comb, k );
(dbx) print *( comb + 22 * 4 )
*(comb+22*4) = 1376259
(dbx) print *( comb + 21 * 4 )
*(comb+21*4) = 21
(dbx) print *( comb + 16 * 4 )
*(comb+16*4) = 16
(dbx) print *( comb + 8 * 4 ) 
*(comb+8*4) = 8
(dbx) print *( comb + 4 * 4 ) 
*(comb+4*4) = 4
(dbx) print *( comb + 2 * 4 ) 
*(comb+2*4) = 2
(dbx) print *( comb + 1 * 4 ) 
*(comb+1*4) = 1
(dbx) print *( comb )        
*comb = 0
(dbx) cont           

execution completed, exit code is 0
(dbx) quit
titan-i386-SunOS5.8 $ 

No core dump.  No problems. 


Let's go back to the T5240 and try a somewhat different compiler
flag set to create a 32-bit binary : 

t5240 $ uname -a 
SunOS node002 5.10 Generic_147440-23 sun4v sparc SUNW,T5240

t5240 $ c99 -Xc -g -errfmt=error -erroff=%none -errwarn=%all -xstrconst 
-xildoff -m32 -xmemalign=8s -xnolibmil -xcode=pic32 -xregs=no%appl -xlibmieee 
-mc -xs -ftrap=%none -Qy -xbuiltin=%none -xunroll=1 -xtarget=generic \
> -D_TS_ERRNO -D_POSIX_PTHREAD_SEMANTICS -D_LARGEFILE64_SOURCE -o 
> combinations_32 combinations.c
t5240 $ file combinations_32 
combinations_32: ELF 32-bit MSB executable SPARC32PLUS Version 1, V8+ Required, 
dynamically linked, not stripped
t5240 $ 
t5240 $ dbx combinations_32 
Reading combinations_32
Reading ld.so.1
Reading libc.so.1
(dbx) stop at 95                                                             
(2) stop at "combinations.c":95
(dbx) run 30 22 > /dev/null
Running: combinations_32 30 22 > /dev/null 
(process id 3806)
stopped in main at line 95 in file "combinations.c"
   95       comb = ( int * ) calloc( (size_t) k, sizeof(int) );
(dbx) print comb          
dbx: warning: cannot recreate macro information for combinations.c -- 
unrecognized compiler : /opt/solarisstudio12.3/prod/bin/c99
comb = (nil)
(dbx) step      
Reading libc_psr.so.1
stopped in main at line 97 in file "combinations.c"
   97       for ( i = 0; i < k; ++i)
(dbx) print comb
comb = 0x21050
(dbx) print *comb
*comb = 0
(dbx) print sizeof(int)
sizeof(int ) = 4
(dbx) print k         
k = 22
(dbx) print ( comb + 22 * 4 )
comb+22*4 = 0x211b0
(dbx) print ( comb + 21 * 4 )
comb+21*4 = 0x211a0
(dbx) stop at 101          
(3) stop at "combinations.c":101
(dbx) cont       
stopped in main at line 101 in file "combinations.c"
  101       printc( comb, k );
(dbx) print *( comb + 21 * 4 )
*(comb+21*4) = 21
(dbx) print *( comb + 16 * 4 )
*(comb+16*4) = 16
(dbx) print *( comb + 8 * 4 ) 
*(comb+8*4) = 8
(dbx) print *( comb + 1 * 4 )
*(comb+1*4) = 1
(dbx) print *( comb )      
*comb = 0
(dbx) cont         

execution completed, exit code is 0
(dbx) quit
t5240 $ 

Again, no core dump, no problems. 

On the T5240 .. watch this : 

t5240 $ ./combinations_32 30 22 > /dev/null
t5240 $ 

No problem. 

t5240 $ ./combinations_32 30 22 > /tmp/big_case_C22of30.dat

So there is a problem ... but not in pointers. At least, I don't
see consistent behavior between Solaris 10, Solaris 8, RHEL and
also inconsistent behavior between a 64-bit binary and a 32-bit
binary. 

> causing heap corruption, which leads to the core dump.
> 
> The line should read:
>          *( comb + i ) = i;

Well this was a post to a website that seems "educational" or at least an on 
going discussion about the topic. I thought that using the syntax *(comb + 
offset ) was more clear than comb[j].

> You were just lucky that it worked at all
> with the first set of parameters.

The problem is .. it works everywhere on Linux. On Red Hat Enterprise Linux. On 
Debian linux also. Only on Solaris 10 with the exact same parameters does it 
segfault.  On Solaris 8 i386 this thing runs. That was what really bothered me. 
I hacked this up on a RHEL workstation first and then took it over to Solaris 
10 on a T5240 where it ran just fine about twenty times .. until I hit this 
case. 

Anyways, there is something odd going on here between Solaris 10, Solaris 8 and 
RHEL. 

Dennis 

_______________________________________________
opensolaris-code mailing list
opensolaris-code@opensolaris.org
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code

Reply via email to