2010-02-08 3 views
2

Код:Почему я не могу использовать этот код для перезаписи строки?

#include "stdio.h" 
#include "string.h" 

int main() 
{ 
    char *p = "abc"; 
    printf("p is %s \n", p); 
    return 0; 
} 

Выход:

p is abc

Код:

#include "stdio.h" 
#include "string.h" 

int main() 
{ 
    char *p = "abc"; 
    strcpy(p, "def"); 
    printf("p is %s \n",p); 
    return 0; 
} 

Выход:

Segmentation fault (core dumped)

Может кто-нибудь объяснить, почему это происходит?

+1

В качестве альтернативы вы имеете директивы '# include', которые ищут локальные файлы (в том же каталоге или в каталоге, указанном' -I' при компиляции). Это системные библиотеки, поэтому вы можете использовать '<>' вместо '' ''.Я не знаю вашу установку сборки, но она должна сделать вещи менее сложными, чтобы не беспокоиться о том, чтобы специально использовать '-I' во всех ваших системных каталогах. –

ответ

1

Потому что p указывает на постоянное запоминающее устройство.

Переписывание данных, которые p указывают на результат неопределенного поведения. Строковый литерал - это любая строка, которую вы явно указываете в кавычках. Все строковые литералы доступны только для чтения. (Примечание: Вы можете использовать строковой литерал для инициализации массива символов.)

Вы должны вместо этого выделить свой собственный буфер, как это:

char buffer[4]; 
strcpy(buffer, "def"); 
printf("buffer is %s \n", buffer); 
7

В коде:

char *p="abc"; 

р указывает на строковый литерал - вам не разрешено изменять строковые литералы, что и делает ваш вызов strcpy. Вместо этого сделайте p массив:

char p[] = "abc"; 

, который скопирует литерал во что-то, что вы можете изменить.

+0

вам не разрешено изменять строковые литералы - ПОЧЕМУ? – aks

+2

@aks Потому что C Standard так говорит. Мысль состоит в том, что компилятор может поместить их в постоянную память. Тем не менее, стандарт не требует, чтобы компиляция диагностировала такие проблемы, как ваша, - это говорит о том, что вы получаете «неопределенное поведение», в вашем случае - ошибка seg. – 2010-02-08 16:43:23

4

Поскольку p указывает на только для чтения области памяти (сегмент __TEXT) в которой содержит строку «abc».

Как вы strcpy это, только для чтения область памяти будет перезаписана, что является незаконным. Таким образом, ядро ​​будет SegFault вашей программой.

Если вы хотите записываемый память, вам нужно выделить его в стек

char p[1024] = "abc"; 

или на куче

char* p = malloc(1024); 
... 
free(p); 

или в сегменте __DATA (т.е. глобальная переменная)

static char p[1024] = "abc"; 
+0

Не обязательно должен быть раздел ТЕКСТ. Многие помещают его в отдельные разделы только для чтения (rdata, rodata и т. Д.). Просто сидение, поскольку основной момент, как вы указали, - только для чтения. – joveha

+0

@joveha: Поскольку я не знаю формат ELF, я просто рассматриваю случай в Mach-O :). В Mach-O эти вещи помещаются в __TEXT, __ const разделе, я думаю. – kennytm

0

p - это в основном просто указатель на данные только для чтения (который является «abc» в вашем случае). Вы не можете перезаписать это с помощью «def».

Смежные вопросы