2010-11-02 4 views
8

В то время как я работал над заданием, я пришел, чтобы знать, что мы не должны использовать задание, такие как:Зачем нам нужен strdup()?

char *s="HELLO WORLD"; 

Программа, использующая такой синтаксис склонна по отношению к врезаться.

Я попробовал и использовал:

int fun(char *temp) 
{ 
    // do sum operation on temp 
    // print temp. 
    } 
    fun("HELLO WORLD"); 

Даже выше работы (хотя вывод компилятора и стандартна относительна).

Вместо этого мы должны попытаться strdup() или использовать Const символ *

Я пытался читать другие подобные вопросы на блоге, но не могли получить концепцию, ПОЧЕМУ ВЫШЕ КОД не должен РАБОТУ.

Является ли память выделенной ?? И какая разница делает const?

+1

Подсказка: что означает «const char *» означает «char *» и почему использовать его в приведенном выше примере полезно (например, как может * доступ * или * изменение * s1 «вызвать сбой»)? Что позволяет strdup делать с «const char *»? – 2010-11-02 16:37:12

+0

'char * s =" HELLO WORLD "' является инициализацией, а не назначением. Во всяком случае, почему вы думаете, что это плохо? – qrdl

ответ

11

Позволяет немного прояснить ситуацию. Вам особо не нужны strdup. Это просто функция, которая выделяет копию char* в куче. Это можно сделать разными способами, в том числе с буферами на основе стека. Вам нужен результат, измененная копия char*.

Причина того, что код, который вы указали, опасен, заключается в том, что он передает то, что на самом деле является постоянной строкой из строки литерала в слот, который ожидает изменчивую строку. Это, к сожалению, допускается в стандарте C, но опасно. Запись в постоянную строку приведет к неожиданным результатам и часто приводит к сбоям. Функция strdupустраняет проблему, поскольку она создает изменяемую копию, которая помещается в слот, ожидающий изменчивую строку.

+0

Итак, если я не пытаюсь изменить строку (например, просто распечатать печать), тогда безопасно использовать такие litterals без consts? – letsc

+0

@smartmuki является законным в соответствии со стандартом, но только для соображений обратной совместимости и по-прежнему является опасным преобразованием. Если вы определяете функцию, которая не мутирует строку то лучше сделать правильную вещь и объявить ее как 'const char *'. – JaredPar

+0

Я только пробовал с компилятором gcc и показывал ожидаемый результат. Но может ли компилятор дать ошибку сегментации для вышеуказанного? И если это так, то y ?? :( – letsc

4

Строковые литералы хранятся в сегменте данных программы. Манипуляция их указателями изменит строковый литерал, что может привести к ... странным результатам в лучшем случае. Используйте strdup(), чтобы скопировать их в пространство с кучей или стеком.

+0

Даже const char * s = "hello" выделяет пространство для литерала в стеке.И мы используем такой синтаксис для работы (даже в printf (const char * s, VLA). – letsc

+1

@smartmuki: это не выделяет пространство для литерала в стеке, только указатель на литерал находится в стеке. – Darron

+0

@ Darron Извините, что это такое? Если я возьму его для const char * s, то если пространство не выделено в стеке (и ни на кучу), то ли оно фактически выделено (или даже выделено) – letsc

1

Это проблема в C. Хотя строковые литералы char *, вы не можете изменить их, так что они эффективно const char*.

Если вы используете gcc, вы можете использовать -Wwrite-strings, чтобы проверить, правильно ли вы используете строковые литералы.

2

Строковые литералы могут храниться в частях памяти, у которых нет привилегий записи. Попытка написать им приведет к неопределенному поведению. const означает, что компилятор гарантирует, что указатель не написан, гарантируя, что вы не вызываете неопределенное поведение таким образом.

0

Прочтите мой ответ на номер (array & string) Difference between Java and C. Он содержит ответ на ваш вопрос в разделе о строках.

Вам нужно понять, что существует разница между распределением статики и памяти и что вы не прибегаете к тем же пространствам памяти.

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