ошибка в книге или так и задумано
От: jyuyjiyuijyu  
Дата: 19.01.14 06:00
Оценка: -1
Всем привет

тут при чтении книжки наткнулся на странный код...
помедетитировал под отладчиком над ним первый цикл изменяет '\0' в конце строки на 1
и выходит а второй предположительно может шагать по оперативной памяти
очень долго за пределами строки пока не встретит терминатора случайно оказавшегося
где то в оперативной памяти и декрементировав его остановиться


это ошибка автора книги да ?


String^ str = "Nish wrote this book for Manning Publishing";
interior_ptr<Char> ptxt = const_cast< interior_ptr<Char> >(
PtrToStringChars(str));
interior_ptr<Char> ptxtorig = ptxt;
while((*ptxt++)++);
Console::WriteLine(str);
while((*ptxtorig++)--);
Console::WriteLine(str);


You go through the string using a while-loop that increments the pointer as well as
each character until a nullptr is encountered, because the underlying buffer of a
String object is always nullptr-terminated. Next, when you use Console::Write-
Line on the String object, you can see that the string has changed to
Ojti!xspuf!uijt!cppl!gps!Nboojoh!Qvcmjtijoh
You’ve achieved encryption! (Just kidding.) Because you saved the original pointer
in ptxtorig, you can use it to convert the string back to its original form using
another while loop. The second while loop increments the pointer but decrements
each character until it reaches the end of the string (determined by the
nullptr). Now, when you do a Console::WriteLine, you get the original string:
Nish wrote this book for Manning Publishing


книжка тут page 139
Re: ошибка в книге или так и задумано
От: MTD https://github.com/mtrempoltsev
Дата: 19.01.14 06:46
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

String^ str = "Nish wrote this book for Manning Publishing";
interior_ptr<Char> ptxt = const_cast< interior_ptr<Char> >(PtrToStringChars(str));
interior_ptr<Char> ptxtorig = ptxt;
while((*ptxt++)++);
Console::WriteLine(str);
while((*ptxtorig++)--);
Console::WriteLine(str);


Фамилия автора говорящая — Nishant Sivakumar.
Re[2]: ошибка в книге или так и задумано
От: uncommon Ниоткуда  
Дата: 19.01.14 06:55
Оценка:
Здравствуйте, MTD, Вы писали:

MTD>Фамилия автора говорящая — Nishant Sivakumar.


http://voidnish.wordpress.com/
Re: ошибка в книге или так и задумано
От: TarasB  
Дата: 20.01.14 08:00
Оценка: +1 :)
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>while((*ptxt++)++);

J>while((*ptxtorig++)--);

Я кончил!
Re[2]: ошибка в книге или так и задумано
От: Figaro Россия  
Дата: 20.01.14 15:51
Оценка:
Спасибо за интимные подробности... Следующий раз напишите статью на РСДН — сразу как кончите
avalon/1.0.433
Re: ошибка в книге или так и задумано
От: Кодт Россия  
Дата: 20.01.14 16:42
Оценка: 6 (3)
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>это ошибка автора книги да ?


Конечно, да. Ты посмотри внимательно, что он пишет:

You go through the string using a while-loop that increments the pointer as well as each character until a nullptr is encountered, because the underlying buffer of a String object is always nullptr-terminated.

Если Сивакумар путает nullptr и '\0' (он же ASCII-код NUL), то что уж тут говорить.
Причём я догадываюсь, как именно он спутал. В эпоху до С++11 нуль-указатель был NULL, и много кто смешивали в литературе NULL и NUL; тем более, что компилятор прощал ошибку вида
char c;
... if(c == NULL) ...

Но вот захотелось товарищу Сивакумару привести всё к современному виду, а получился энциклонг.
Перекуём баги на фичи!
Re[2]: ошибка в книге или так и задумано
От: jyuyjiyuijyu  
Дата: 20.01.14 17:10
Оценка:
Здравствуйте, Кодт, Вы писали:

у меня еще закрались сомнения так как автор пишет про .NET String^ то может и правда их внутренний буфер заканчивается не двумя байтами которые представляют в юникод строках '\0' а 4 или 8 в зависимости от платформы так как он упомянул nullptr


но во первых даже если это и так то после работы второго цикла на x86 машине в памяти вместо \x00\x00\x00\x00 будет уже \x00\x00\xFF\xFF тоесть в любом случае остается "побочный эффект" от этих циклов даже если предположить что писал он это исходя из того что зарубился что в конце строки всегда кусок памяти размером с указатель на этой платформе

а во вторых такой код повредит память в "обычном" C++ так как во втором цикле пока ищет '\0' где то в оперативной памяти (так как свой превратил в FF в певом цикле) попутно будет декрементировать каждый байт уже чужой памяти
Re[3]: ошибка в книге или так и задумано
От: TarasB  
Дата: 21.01.14 08:49
Оценка:
Здравствуйте, Figaro, Вы писали:

F>Спасибо за интимные подробности... Следующий раз напишите статью на РСДН — сразу как кончите


Статью о том, почему не надо в одном выражении использовать 100500 экскрементов? Так уже сто раз всё написано везде. Но придуркам, желающим показать свою кулхацкерность, эти статьи не указ.

Этот же кусок можно переписать так:
for (;;)
{
  if (!(*ptxt)) break;
  ++(*ptxt);
  ++ptxt;
}

заодно исправал баг с порчей нуля на конце
Re[4]: ошибка в книге или так и задумано
От: Кодт Россия  
Дата: 21.01.14 10:23
Оценка:
Здравствуйте, TarasB, Вы писали:

TB>заодно исправал баг с порчей нуля на конце


Вот так будет правильнее
#include <stdio.h>

int main() {
#define ENCODE      ((*p++)++)
#define ENCODE_UNDO (--(*--p))
#define DECODE      (--(*p++))

char* p;
char s[] = "hello world\0 hic sunt dracones! \0\1\xff";

printf("s=[ %s ]\n", s);

p = s;
while(ENCODE);
ENCODE_UNDO;
printf("e=[ %s ]\n", s);
ENCODE;

p = s;
while(DECODE);
printf("d=[ %s ]\n", s);

return 0;
}
Перекуём баги на фичи!
Re[5]: ошибка в книге или так и задумано
От: TarasB  
Дата: 21.01.14 10:51
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, TarasB, Вы писали:


TB>>заодно исправал баг с порчей нуля на конце


К>Вот так будет правильнее


С точки зрения обфускации кода — да.
Re: ошибка в книге или так и задумано
От: CEMb  
Дата: 23.01.14 02:27
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>Всем привет


J>тут при чтении книжки наткнулся на странный код...

J>помедетитировал под отладчиком над ним первый цикл изменяет '\0' в конце строки на 1
J>и выходит а второй предположительно может шагать по оперативной памяти
J>очень долго за пределами строки пока не встретит терминатора случайно оказавшегося
J>где то в оперативной памяти и декрементировав его остановиться


J>это ошибка автора книги да ?


Это всё от нетерпимости по национальному признаку!
Надо написать гневное письмо в комитет об ущемлении прав индусов — пусть внесут в стандарт требование двойного нуля в конце однобайтных строк — тогда несомненно гениальная программа сразу станет работать корректно!
Re: ошибка в книге или так и задумано
От: __kot2  
Дата: 23.01.14 07:20
Оценка:
не надо вообще такие книжки читать
Re[2]: ошибка в книге или так и задумано
От: Кодт Россия  
Дата: 23.01.14 10:08
Оценка: :)
Здравствуйте, CEMb, Вы писали:

CEM>Это всё от нетерпимости по национальному признаку!

CEM>Надо написать гневное письмо в комитет об ущемлении прав индусов

Не написать, а надиктовать аудиозапись на ингрише.
Хотя, написать им на руинглише тоже непогано будет.

CEM>пусть внесут в стандарт требование двойного нуля в конце однобайтных строк — тогда несомненно гениальная программа сразу станет работать корректно!


Терминатором должен быть \0\0\1\1\377\377 — тогда гораздо больше гениальных программ смогут работать корректно.
Перекуём баги на фичи!
Re[3]: ошибка в книге или так и задумано
От: TarasB  
Дата: 23.01.14 10:11
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Терминатором должен быть \0\0\1\1\377\377 — тогда гораздо больше гениальных программ смогут работать корректно.


377?
Re[4]: ошибка в книге или так и задумано
От: Кодт Россия  
Дата: 23.01.14 14:20
Оценка:
Здравствуйте, TarasB, Вы писали:

К>>Терминатором должен быть \0\0\1\1\377\377 — тогда гораздо больше гениальных программ смогут работать корректно.


TB>377?


while(++*str++);
Перекуём баги на фичи!
Re[5]: ошибка в книге или так и задумано
От: CEMb  
Дата: 24.01.14 03:10
Оценка:
Здравствуйте, Кодт, Вы писали:

К>>>Терминатором должен быть \0\0\1\1\377\377 — тогда гораздо больше гениальных программ смогут работать корректно.


тогда уж надо в стандарте разрешить всем использовать свои стандарты

TB>>377?


К>
while(++*str++);


Это конструкция упаковывает 377 в байт, дааа боюсь, коллега, мы можем так уйти за радиус Шварцшильда в байте и свернём в бит всю информационную вселенную!
Re[6]: ошибка в книге или так и задумано
От: Кодт Россия  
Дата: 24.01.14 07:48
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Это конструкция упаковывает 377 в байт, дааа боюсь, коллега, мы можем так уйти за радиус Шварцшильда в байте и свернём в бит всю информационную вселенную!


1) Не позорься
2) Проверься на баги в своих программах
Потому что грабельки-то детские. Но ударить могут больно.

Хотя конечно, char у нас знаковый, а отрицательные коды в строках сделать нельзя, поэтому неизбежно устраиваем целочисленное переполнение через верхнюю границу ASCII \177.
Но это должно быть законно. (лень лезть в стандарт за номерами параграфов).
Перекуём баги на фичи!
Re[6]: ошибка в книге или так и задумано
От: TarasB  
Дата: 24.01.14 07:59
Оценка:
Здравствуйте, CEMb, Вы писали:


CEM>Это конструкция упаковывает 377 в байт, дааа


Я только вчера узнал, что это 8-ичная система.
Re[7]: ошибка в книге или так и задумано
От: Кодт Россия  
Дата: 24.01.14 09:18
Оценка: +1
К>2) Проверься на баги в своих программах
К>Потому что грабельки-то детские. Но ударить могут больно.

На всякий случай: я имею в виду, что
assert('\20' == 20); // assert failed

а не бешеные автоинкременты
Перекуём баги на фичи!
Re[7]: ошибка в книге или так и задумано
От: CEMb  
Дата: 24.01.14 10:10
Оценка:
Здравствуйте, Кодт, Вы писали:

CEM>>Это конструкция упаковывает 377 в байт, дааа боюсь, коллега, мы можем так уйти за радиус Шварцшильда в байте и свернём в бит всю информационную вселенную!


К>1) Не позорься

К>2) Проверься на баги в своих программах
К>Потому что грабельки-то детские. Но ударить могут больно.

К>Хотя конечно, char у нас знаковый, а отрицательные коды в строках сделать нельзя, поэтому неизбежно устраиваем целочисленное переполнение через верхнюю границу ASCII \177.

К>Но это должно быть законно. (лень лезть в стандарт за номерами параграфов).

А, понял, в чём дело... я не пользуюсь восьмеричным форматом, я всё в хексе пишу. И таких граблей у меня нету. А возможностями переполнения сам пользуюсь.

А про радиус Шварцшильдта для байта была прикольная шутка "Как сделать dev/nul? Берём любой байт..."
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.