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/