Yes, I agree with you -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20080106/efb1c465/attachment.html>
but why this code don't work:
; ModuleID = 'sample.lz'
@.str1 = internal global [6 x i8] c"world\00" ; <[6 x
i8]*>
[#uses=1]
@.str2 = internal global [7 x i8] c"hello \00" ; <[7 x
i8]*>
[#uses=1]
@.str7 = internal global [7 x i8] c"father\00" ; <[7 x
i8]*>
[#uses=1]
@.str8 = internal global [8 x i8] c"mother \00" ; <[8 x
i8]*>
[#uses=1]
declare i32 @puts(i8*)
declare i8* @strcat(i8*, i8*)
declare i32 @strlen(i8*)
declare void @llvm.memcpy.i32(i8*, i8*, i32, i32)
define i32 @main() {
mainBlock:
%str3 = getelementptr [7 x i8]* @.str2, i64 0, i64 0 ;
<i8*> [#uses=2]
%str4 = getelementptr [6 x i8]* @.str1, i64 0, i64 0 ;
<i8*> [#uses=1]
call i8* @strcat( i8* %str3, i8* %str4 ) ; <i8*>:0
[#uses=0]
%tmp6 = call i32 @puts( i8* %str3 ) ; <i32> [#uses=0]
%str9 = getelementptr [8 x i8]* @.str8, i64 0, i64 0 ;
<i8*> [#uses=2]
%str10 = getelementptr [7 x i8]* @.str7, i64 0, i64 0 ;
<i8*> [#uses=1]
call i8* @strcat( i8* %str9, i8* %str10 ) ; <i8*>:1
[#uses=0]
%tmp12 = call i32 @puts( i8* %str9 ) ; <i32> [#uses=0]
ret i32 0
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20080106/4353f37a/attachment.html>
Zalunin Pavel wrote:> but why this code don't work: > > ; ModuleID = 'sample.lz' > @.str1 = internal global [6 x i8] c"world\00" ; <[6 x i8]*> > [#uses=1] > @.str2 = internal global [7 x i8] c"hello \00" ; <[7 x i8]*> > [#uses=1] > @.str7 = internal global [7 x i8] c"father\00" ; <[7 x i8]*> > [#uses=1] > @.str8 = internal global [8 x i8] c"mother \00" ; <[8 x i8]*> > [#uses=1] > > declare i32 @puts(i8*) > > declare i8* @strcat(i8*, i8*) > > declare i32 @strlen(i8*) > > declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) > > define i32 @main() { > mainBlock: > %str3 = getelementptr [7 x i8]* @.str2, i64 0, i64 0 > ; <i8*> [#uses=2] > %str4 = getelementptr [6 x i8]* @.str1, i64 0, i64 0 > ; <i8*> [#uses=1] > call i8* @strcat( i8* %str3, i8* %str4 ) ;Right here you are copying str1 the memory address following the end of str2. Notice that str3 is a pointer to a 7 char array. It doesn't get bigger. You are doing something that is undefined. You need: char result[100]; // big enough not to overflow. strcpy (result, "hello "); strcat (result, "world"); -Rich
On Jan 6, 2008, at 1:20 PM, Zalunin Pavel wrote:> but why this code don't work: >It does work, but you wrote code that violates the C standard and, therefore, it has undefined behavior--code that compiles and code that actually works are two separate things. For instance, on my machine, it produces code that looks like this in the DATA section: .data _.str1: ; '.str1' .asciz "world" _.str2: ; '.str2' .asciz "hello " _.str7: ; '.str7' .asciz "father" _.str8: ; '.str8' .asciz "mother " With the first strcat, you overwrote the "father" string ("_.str7" in this example) with the "world" string ("_.str1" here). Boom! instant undefined behavior. You're lucky; it could have resulted in reformatting your hard drive. :-) -bw> ; ModuleID = 'sample.lz' > @.str1 = internal global [6 x i8] c"world\00" ; <[6 x i8] > *> [#uses=1] > @.str2 = internal global [7 x i8] c"hello \00" ; <[7 x i8] > *> [#uses=1] > @.str7 = internal global [7 x i8] c"father\00" ; <[7 x i8] > *> [#uses=1] > @.str8 = internal global [8 x i8] c"mother \00" ; <[8 x i8] > *> [#uses=1] > > declare i32 @puts(i8*) > > declare i8* @strcat(i8*, i8*) > > declare i32 @strlen(i8*) > > declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) > > define i32 @main() { > mainBlock: > %str3 = getelementptr [7 x i8]* @.str2, i64 0, i64 > 0 ; <i8*> [#uses=2] > %str4 = getelementptr [6 x i8]* @.str1, i64 0, i64 > 0 ; <i8*> [#uses=1] > call i8* @strcat( i8* %str3, i8* %str4 ) ; > <i8*>:0 [#uses=0] > %tmp6 = call i32 @puts( i8* %str3 ) ; <i32> > [#uses=0] > %str9 = getelementptr [8 x i8]* @.str8, i64 0, i64 > 0 ; <i8*> [#uses=2] > %str10 = getelementptr [7 x i8]* @.str7, i64 0, i64 > 0 ; <i8*> [#uses=1] > call i8* @strcat( i8* %str9, i8* %str10 ) ; > <i8*>:1 [#uses=0] > %tmp12 = call i32 @puts( i8* %str9 ) ; <i32> > [#uses=0] > ret i32 0 > } > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
I'm somewhat new here, but if I'm wrong, hopefully someone will chime in :) On Jan 6, 2008, at 3:20 PM, Zalunin Pavel wrote:> but why this code don't work: > > ; ModuleID = 'sample.lz' > @.str1 = internal global [6 x i8] c"world\00" ; <[6 x > i8]*> [#uses=1] > @.str2 = internal global [7 x i8] c"hello \00" ; <[7 x > i8]*> [#uses=1] > @.str7 = internal global [7 x i8] c"father\00" ; <[7 x > i8]*> [#uses=1] > @.str8 = internal global [8 x i8] c"mother \00" ; <[8 x > i8]*> [#uses=1]All of the strings here are allocated with exact sizes for their contents...> declare i32 @puts(i8*) > > declare i8* @strcat(i8*, i8*) > > declare i32 @strlen(i8*) > > declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) > > define i32 @main() { > mainBlock: > %str3 = getelementptr [7 x i8]* @.str2, i64 0, i64 > 0 ; <i8*> [#uses=2] > %str4 = getelementptr [6 x i8]* @.str1, i64 0, i64 > 0 ; <i8*> [#uses=1] > call i8* @strcat( i8* %str3, i8* %str4 ) ; > <i8*>:0 [#uses=0]And here, you're attempting to call strcat on "hello " with "world". strcat does not create a new string, it just writes to the first pointer wherever it finds the first NULL byte. With the first string only having an allocated size of 7, adding 6 more characters will overwrite memory. HTH, Jon -- Jonathan Johnson President Alacatia Labs, Inc. http://www.alacatialabs.com/