Member 12928053 Ответов: 3

Переназначение нового символа на указатель char приведет к сбою.


Код действительно прост.

char *foo = "000"; // foo->"000\0"
*(foo+0) = '1'; // Crash | what i expecting is foo->"100\0"
*(foo+1) = (char)'2'; // Crash | what i expecting is foo->"120\0"
*(foo+2) = '3'; // Crash | what i expecting is foo->"123\0"


ММО

char *foo = "000";

Создайте новый указатель char и указатель на строку "000\0".

*(foo+0) = '1';

или просто
*foo = '1';

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

Что я уже пробовал:

char *foo = malloc(4); // codes work like a charm.
*(foo+0) = '1';
*(foo+1) = '2';
*(foo+2) = '3';
*(foo+3) = '\0';

Эту проблему можно решить с помощью malloc (), но разве предыдущий код не имеет дело со "стеком", а этот-с "кучей"?

3 Ответов

Рейтинг:
2

nv3

Ваш указатель foo выделяется в стеке. Но хранилище, на которое он указывает-строковый литерал "000", - это не так. Вероятно, он находится в защищенной от записи памяти. Это может быть изменено переключателем компилятора (см. документацию по компилятору). Но я бы сказал, что в любом случае это плохая практика-изменять хранение строкового литерала. Использовать как стек или кучу памяти (через malloc или New).

Ниже приведен пример выделенного хранилища:

char buffer[10];
buffer[0] = '1';


CPallini

5.

Рейтинг:
19

User 59241

Строковые литералы рассматриваются как константа в стандарте c (и c++). STR30-C. Не пытайтесь изменять строковые литералы - Sei CERT C Coding Standard - CERT Secure Coding Standards[^]

См. Раздел " Изменение Строковых Литералов": Строковые Литералы C++ [^]

Смотреть также: c++ - почему строковые литералы const? - переполнение стека[^]

Изменение строкового литерала приводит к неопределенному поведению.


CPallini

5.

Member 12928053

Спасибо за Ваше объяснение и достойный ответ "строковых литералов"

Рейтинг:
0

Patrice T

char *foo = "000"; // foo->"000\0"
*(foo+0) = '1'; // Crash | what i expecting is foo->"100\0"
*(foo+1) = (char)'2'; // Crash | what i expecting is foo->"120\0"
*(foo+2) = '3'; // Crash | what i expecting is foo->"123\0"

В этом коде "000" является частью программы и защищен от изменений. Если бы это было разрешено, вы бы в конечном итоге получили самоизменяющуюся программу.

char *foo = malloc(4); // codes work like a charm.
*(foo+0) = '1';
*(foo+1) = '2';
*(foo+2) = '3';
*(foo+3) = '\0';

Здесь вы выделяете некоторую память в пространстве, которое допускает изменения, именно там хранятся ваши переменные данные.

Цитата:
Эту проблему можно решить с помощью malloc (), но разве предыдущий код не имеет дело со "стеком", а этот-с "кучей"?

В обоих кодах указатель находится в стеке,но в первом он указывает на exe-код и не изменяется, во втором данные находятся в куче.