As it stands, I know that dynamically allocated string literals cannot be changed during run-time, otherwise you will hit a segmentation fault.
This is due to the fact that dynamically allocated string literals are stored, from what I saw in the assembly code, in the .rodata
segment, placing these literals in what I interpret as read only memory.
So in theory this should never work on what I hope is in every modern C compiler:
#include <stdio.h>
#include <stdlib.h>
int
main( void )
{
char *p = ( char * )malloc( 10 * sizeof( char ) );
if ( p == NULL )
{
puts( "Bad memory allocation error!" );
return( EXIT_FAILURE );
}
else
{
p = "literal";
printf( "%s\n", p );
p[0] = 't'; // <-- This should cause a segmentation fault!
printf( "%s\n", p ); // <-- This should never reach execution!
}
return( EXIT_SUCCESS );
}
However, upon studying how tolower()
and toupper()
work. I find it rather difficult to understand how these two simple functions are able to do what I thought for a long while was impossible. Here's what I mean:
#include <stdio.h>
int
tolowercase( int c )
{
return ( c >= 'A' && c <= 'Z' ) ? ( c + 32) : ( c );
}
int
retstrlen( char *str )
{
int len = 0;
while( *str != '\0' ) { len++; str++; }
return( len );
}
int
main( int argc, char **argv )
{
for( int i = 0; i < argc; i++ )
{
for( int j = 0; j < retstrlen( argv[i] ); j++ )
{
argv[i][j] = tolowercase( argv[i][j] );
printf( "%c", argv[i][j] );
}
printf( "\n" );
}
return 0;
}
How does the source code defined in my custom tolower()
function not cause a segmentation fault as it normally would through manipulating dynamically allocated string literals?
My only hypothesis that I can draw is that since tolowercase()
has a parameter of int, and a return type of int, then the compiler performs a type conversion which indirectly manipulates **argv.
I am pretty sure I am on the right track about this, yet I could have gotten my whole terminology wrong here, so what is really happening to **argv?