LINUX.ORG.RU

Pointer dereference + postincrement, будет ли UD?

 , ,


0

2

Зравствуйте!

Есть задача разбить строку вида <login>/<password> на две. Делаю вот так:

char *login = getInput(); // getInput возвращает сабжевую строку
char *password = strchr(login, '/');
if (! password) {
    // handle error
}
*password++ = '\0';

printf("login: %s\npassword: %s\n", login, password);

Всё бы хорошо, но одна строчка вызывает подозрение на UD:

*password++ = '\0';
Данная строчка должна заменить '/' на '\0'. Но где-то я слышал, что постинкремент укразателя как lvalue может вызвать UD.

постинкремент укразателя как lvalue

...а так же много других страшных и непонятных слов...

ub не будет, но так пишут только мудаки

anonymous
()

кстати, не забивай голову, вспомни классиков:

void strcpy(char* d, char* s)
{
  while(*d++ = *s++);
}

emulek
()

Почему бы не сделать отдельно login и отдельно password?

Вторая проблема это непонятно как высвобождать память. Точнее, тем кто придёт после тебя может быть непонятно почему free(login) есть, а free(password) нету.

Ну так работать будет, конечно. Но, имхо, лучше пожертвовать кол-вом строк в пользу бОльшей очевидности и прозрачности кода.

true_admin ★★★★★
()
Ответ на: комментарий от emulek

заметь, я даже не спрашиваю в какой вселенной пароль ходит в одной строке с логином plain-text-ом

anonymous
()

The strchr() function returns a pointer to the first occurrence of the character c in the string s

*password++ = '\0';

Данная строчка должна заменить '/' на '\0'

я чего-то не понимаю?

unt1tled ★★★★
()

А что тут не нравится?

*password++ = '\0';

1. Выполнился инкремент, возвратил старое значение.

2. Выполнилось разименование старого значения.

3. По старому значению присвоился \0.

Все нормально.

grondek
()
Последнее исправление: grondek (всего исправлений: 1)
Ответ на: комментарий от anonymous

я даже не спрашиваю в какой вселенной пароль ходит в одной строке с логином plain-text-ом

заметь, мы тут совсем другую проблему обсуждали.

Почему бы не сделать отдельно login и отдельно password?

может это совсем не логин/пароль?

Вторая проблема это непонятно как высвобождать память. Точнее, тем кто придёт после тебя может быть непонятно почему free(login) есть, а free(password) нету.

может это static переменная? Или там свой alloc с GC и подсчётом ссылок?

Ну так работать будет, конечно. Но, имхо, лучше пожертвовать кол-вом строк в пользу бОльшей очевидности и прозрачности кода.

ТС спрашивал не об этом. Этот отрывок ни о чём не говорит. Отрывок — просто отрывок.

emulek
()
Ответ на: комментарий от KennyMinigun

это махровый Ънтерпрайз

алсо, сам такое видел.

emulek
()
Ответ на: комментарий от grondek

в PDP была команда, которое такое _сразу_ делает. С любым регистром. Потому это было годно. Сейчас это тоже годно, ибо компилятор отлично знает эту классическую идиому из K&R.

emulek
()
Ответ на: комментарий от emulek

может это совсем не логин/пароль?

А что ещё может быть в переменных login и password?

может это static переменная? Или там свой alloc с GC и подсчётом ссылок?

Пусть ТС лучше скажет. Я использовал хрустальный шар и он говорит мне что там ручное управление памятью. Алсо, такое использование памяти может сбить GC с толку.

ТС спрашивал не об этом.

Я знаю, это мои пять копеек.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

Пусть ТС лучше скажет. Я использовал хрустальный шар и он говорит мне что там ручное управление памятью. Алсо, такое использование памяти может сбить GC с толку.

он уже сказал, там у его

DESCRIPTION The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).

Я знаю, это мои пять копеек.

да, я был неправ.

emulek
()
Ответ на: комментарий от KennyMinigun

тут тоже можно код вставлять для Ъ

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
int main(void) {
char *login = strdup("login/password"); // getInput возвращает сабжевую строку
char *password = strchr(login, '/');
if (! password) {
fputs("Cannot parse", stderr);
exit(EXIT_FAILURE);
}
 
*password++ = '\0'; // ①
 
printf("login: %s\npassword: %s\n", login, password);
 
// your code goes here
return 0;
}

короче, не трогай это говно. В строке ① UB не будет, это точно. В остальном читай вышеотписавшихся.

UPD отступы побились, но хуже не стало.

emulek
()
Последнее исправление: emulek (всего исправлений: 1)
Ответ на: комментарий от true_admin

Пусть ТС лучше скажет. Я использовал хрустальный шар и он говорит мне что там ручное управление памятью.

Если вкратце,то да: там самописный аллокатор + объект контекста. Сабжевый вызов происходит в main, а getInput возвращает указатель на элемент (единожды) скопированного argv.

KennyMinigun ★★★★★
() автор топика
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от emulek

strdup в коде примера я использовал, чтоб не модифицировать строковую константу, ибо это UB. Хотя можно было для каноничности сделать так:

char login[] = "login/password"; 

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

чтоб не модифицировать строковую константу, ибо это UB.

не, это не UB. Тут тебе сразу система по рукам даст(программу грохнет), если ты туда полезешь, так только в MS-DOS можно было баловаться ☺

я понял, что мне в твоём коде не нравится: для этого есть стандартная strtok(3). Читай ман, там и примерчик есть.

emulek
()
Ответ на: комментарий от emulek

ы напился — понял

нельзя на работе в пятницу думать

unt1tled ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.