views:

135

answers:

2

Hi,

Below code crash in VS 2010 when you compile with following flag and if you add /GF- or remove the opimization flag they don't crash. The crash occur at assembly code which translate 'if( path[i] == '/' )'. I like to understand the optimization that compiler does here and lead to crash. Looking forward for some pointers.

-Karthik

cl.exe /MD /O2 test.c

// Test.c

#include <stdio.h>

#include  <string.h>

void testpath(char* path, int bufsiz)  
{  

    int i;  

    printf("%p\n", path);  
    for( i=0; i`<`strlen(path); i++ ) {  
      if( path[i] == '/' ) {  
         path[i] = '\\';  
     }  
  }  
}

int main()  
{  

    const char* path = "testexport.prj";  
    char *path1 = "testexport.prj";  
    printf("%p\n", path);  
    printf("%p\n", path1);  
    testpath(path, 1024);  
}  
+4  A: 

You try to modify a string literal, that's undefined behavior.

 const char* path = "testexport.prj";
 testpath(path, 1024);
 // then later:
 void testpath(char* path, int bufsiz)
 {
     int i;  
     for( i=0; i`<`strlen(path); i++ ) {  
     if( path[i] == '/' ) {  
         path[i] = '\\';// <<<<<< UB here
     }  
 }  

string literals are usually stored in read-only memory, so on your implementation an attempt to modify a string literal results in access violation that crashes your program.

sharptooth
Thanks for your reply. I understand modifying 'string' literal leads to unspecified behavior. But my point why an optimized build lead to crash when the string literal doesn't get modified due to conditional check 'path[i] == '/'' in the code. Can you please comment about it?
Kartlee
@Kartlee: When optimization is on you can't be sure which line you're on when you debug, so the most likely explanation is that you misinterpret the results of the debug session. To be sure modify the if-statement: `if( path[i] == '/' ) { printf( "gonna modify\n" ); path[i] = '\\'; } so that there's a debug print before a modification attempt. I'm pretty sure the program will crash exactly after the modification attempt.
sharptooth
+7  A: 

Trying to modify the contents of a string literal invokes Undefined Behaviour.

From ISO C99 (Section 6.4.5/6)

It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined

From ISO C++-98 (Section 2.13.4/2)

Whether all string literals are distinct(that is, are stored in non overlapping objects) is implementation defined. The effect of attempting to modify a string literal is undefined.

On most implementations (including MSVC) this results to crash of your application.

Prasoon Saurav
Thanks for your reply. I understand modifying 'string' literal leads to unspecified behavior. But my point why an optimized build lead to crash when the string literal doesn't get modified due to conditional check 'path[i] == '/'' in the code. Can you please comment about it?
Kartlee
@Kartlee: path[i] = '\\'; tries to modify the contents of the string literal and this leads to crash of your application and yes the behavior is undefined.(not unspecified). :) The conditional check is just fine IMHO.
Prasoon Saurav
It is a real surprise when string literal which doesn't enter the code which modify it due to conditional check will lead to crash. Did you get a chance to see the assembly code what exactly happens here? If you turn off string pooling, they don't lead to crash. I suspect if the compiler does any lookahead to check if string literal gets modified when string pooling is turned on.
Kartlee