This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/15508] Size evaluation of variable-length array seem to be skipped in some cases.


------- Additional Comments From takashi dot yano at nifty dot ne dot jp  2004-05-20 17:21 -------
(In reply to comment #10)
> The comments are pretty confusing. Can we have a recap? What is exactly the 
bug?

Thanks. I'd like to re-explain with some additional stuffs.

Problem:
Assertion at line 12 fails if r>=5. I have studied on assembler source code
generated by "g++ -Wall -S pr15508.cc", and found that:

The 'void func(int)' in the simple test program shown in the report needs
the size of variable length array 'int [r]' in execution. G++ 2.96 and 3.3.1
generate codes which evaluate it in 'if' block at line 9 to get address of
'a[1][0]'. The size evaluation result for 'int [r]' is needed to get pointer
'a[1]' also at line 11 and 12. The result evaluated at line 9 is reused
here. But the evaluation at line 9 is executed only when r<5. If r>=5, the
evaluation result is used in spite of being not evaluated yet. As a result,
the assertion at line 12 fails though it should always succeed. Also this
can cause segmentation fault when trying to access *a[1].

Source Code:
1: // Filename: pr15508.cc
2: #include <iostream>
3: #include <cassert>
4:
5: void func(int r)
6: {
7: 	int (*a)[r] = new int [2][r];
8:
9: 	if (r<5) a[1][0] = 0;
10:
11: 	std::cout << r << '\t' << a[1] - a[0] << std::endl;
12: 	assert( a[1] - a[0] == r);
13:
14: 	delete [] a;
15: }
16:
17: int main()
18: {
19: 	for (int i=1; i<10; i++) func(i);
20: 	return 0;
21: }


Reference (func() part of pr15508.s by v2.96):
.text
	.align 4
.globl func__Fi
	.type  func__Fi,@function
func__Fi:
.LFB1:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	subl	$8, %esp
.LCFI2:
	subl	$12, %esp
; int (*a)[r] = new int [2][r];
	movl	8(%ebp), %eax	; eax: r (read from 8(%ebp))
	movl	%eax, %eax
	sall	$3, %eax	; eax: r*2*sizeof(int) (size of 'int [2][r]')
	subl	$8, %eax
	addl	$8, %eax
	pushl	%eax
.LCFI3:
	call	__builtin_vec_new
	addl	$16, %esp
	movl	%eax, -4(%ebp)	; store address(a);
; if (r<5)
	cmpl	$4, 8(%ebp)
	jg	.L3
	; Evaluating size of 'int [r]'
	movl	8(%ebp), %eax	; eax: r (read from 8(%ebp))
	movl	%eax, %eax
	sall	$2, %eax	; eax: r*sizeof(int);
	subl	$4, %eax
	addl	$4, %eax
	movl	%eax, -8(%ebp)	; Store size of 'int [r]' to -8(%ebp)
; a[1][0] = 0;
	movl	-4(%ebp), %eax	; eax: address(a)
	movl	-8(%ebp), %edx	; edx: address offset of a[1][0]
	movl	$0, (%edx,%eax)	; a[1][0] = 0
.L3:
; std::cout << r << '\t' << a[1] - a[0] << std::endl;
	subl	$8, %esp
	pushl	$endl__FR7ostream
	subl	$12, %esp
	; calculate 'a[1] - a[0]'
	movl	-8(%ebp), %eax	; eax: size of 'int [r]' (restore from -8(%
ebp))
	addl	-4(%ebp), %eax	; eax: address(a[1])
	subl	-4(%ebp), %eax	; eax: address(a[1]) - address(a[0])
	movl	%eax, %eax
	sarl	$2, %eax	; eax: a[1] - a[0] 
	pushl	%eax
	subl	$12, %esp
	pushl	$9		; '\t'
	subl	$12, %esp
	pushl	8(%ebp)		; r
	pushl	$cout
.LCFI4:
	call	__ls__7ostreami
	addl	$20, %esp
	movl	%eax, %eax
	pushl	%eax
	call	__ls__7ostreamc
	addl	$20, %esp
	movl	%eax, %eax
	pushl	%eax
	call	__ls__7ostreami
	addl	$20, %esp
	movl	%eax, %eax
	pushl	%eax
.LCFI5:
	call	__ls__7ostreamPFR7ostream_R7ostream
	addl	$16, %esp
; assert( a[1] - a[0] == r);
	movl	-8(%ebp), %eax	; eax: size of 'int [r]' (restore from -8(%
ebp))
	addl	-4(%ebp), %eax	; eax: address(a[1])
	subl	-4(%ebp), %eax	; eax: address(a[1]) - address(a[0])
	movl	%eax, %eax
	sarl	$2, %eax	; eax: a[1] - a[0]
	cmpl	8(%ebp), %eax	; compare (a[1] - [0]) and r (read from 8(%
ebp))
	je	.L5
	pushl	$__PRETTY_FUNCTION__.418
	pushl	$12
	pushl	$.LC0
	pushl	$.LC1
	call	__assert_fail
	.p2align 2
.L5:
	cmpl	$0, -4(%ebp)
	je	.L8
	subl	$12, %esp
	pushl	-4(%ebp)
	call	__builtin_vec_delete
	addl	$16, %esp
.L8:
	leave
	ret


Additional Information:
The code below works well.

void func(int r)
{
	typedef int vla[r];
	vla *a = new vla [2];

 	if (r<5) a[1][0] = 0;

	std::cout << r << '\t' << a[1] - a[0] << std::endl;
	assert( a[1] - a[0] == r);

	delete [] a;
}


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15508


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]