Home > Software engineering >  Why am I able to change string literal defined inside a struct?
Why am I able to change string literal defined inside a struct?

Time:09-19

typedef struct node
{
    char *name;
}
node;

int main(void)
{
    node *temp = malloc(sizeof(node));
    node *table[2];

    table[0] = temp;
    table[0]->name = "tamesh";
    
    printf("%c \n",  toupper(table[0]->name[0]));
}

I am able to print the output "T". But technically I should not be able to modify a string literal right?

CodePudding user response:

You are not able to do that (anything which looks like that is undefined behaviour), and you do not.
You are only printing the char return value of a called function. You do not change the string literal; the called function (e.g. according to https://en.cppreference.com/w/c/string/byte/toupper ) doesn't either.

CodePudding user response:

On many systems like Linux, string literals are grouped into a read-only section. In this context, a tool like objdump provides the ability to look at the content of the generated object after compilation/linking. For example, if the resulting executable is named str, the following is output to show that the string literal is stored in a section called ".rodata" (which means read-only data):

$ objdump -s str

str:     file format elf64-x86-64
[...]
Contents of section .rodata:
 2000 01000200 74616d65 73680025 63200a00  ....tamesh.%c ..
[...]

In the above dump, we can see that even the string literal "%c \n" passed to printf() is located into this section.
At execution time, the corresponding memory area will be write protected. Any attempt to write into this section will result into a segmentation violation error.
As said in the comments and other answers, your original code does not modify the string, it merely passes the first char of the string to toupper() which displays the upper case translation of its parameter. Let's do a real modification of the string:

#include <stdio.h>  // For printf()
#include <ctype.h>  // For toupper()
#include <stdlib.h> // For malloc()

typedef struct node
{
    char *name;
}
node;

int main(void)
{
    node *temp = malloc(sizeof(node));
    node *table[2];

    table[0] = temp;
    table[0]->name = "tamesh";
    
    printf("%c \n",  toupper(table[0]->name[0]));

    table[0]->name[0] = 'T';

    return 0;
}

The execution triggers a segmentation fault error:

$ gcc -g str.c -o str
$ ./str
T 
Segmentation fault (core dumped)

The analysis of the resulting core file with a debugger like gdb shows that the crash occured at the line where we tried to modify the string:

$ gdb str core
[...]
Type "apropos word" to search for commands related to "word"...
Reading symbols from str...
[New LWP 7273]
Core was generated by `./str'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  main () at str.c:21
21      table[0]->name[0] = 'T';
(gdb) where
#0  main () at str.c:21
(gdb) 
  • Related