LINUX.ORG.RU

Функция удаляет массив

 , ,


1

2

Есть такая вот функция

int osmo_hexparse(const char *str, uint8_t *b, int max_len)

{
	int i, l, v;

	l = strlen(str);
	if ((l&1) || ((l>>1) > max_len))
		return -1;

	memset(b, 0x00, max_len);

	for (i=0; i<l; i++) {
		char c = str[i];
		if (c >= '0' && c <= '9')
			v = c - '0';
		else if (c >= 'a' && c <= 'f')
			v = 10 + (c - 'a');
		else if (c >= 'A' && c <= 'F')
			v = 10 + (c - 'A');
		else
			return -1;
		b[i>>1] |= v << (i&1 ? 0 : 4);
	}

	return i>>1;
}

Вторым аргументом я в неё передаю вот такую переменную

uint8_t *b = malloc(20);
Память выделяется успешно, проверял, обратиться можно к любому байту. Вызов osmo_hexparse отрабатывает успешно, возвращает 20. Да вот беда, после этого вызова обращение к любому байту b кроме b[0] вызывает сегфолт. Чего такого нехорошего сделала данная ф-ция с массивом

★★★

Последнее исправление: cetjs2 (всего исправлений: 1)
int main()
{
	const char *str = "45AF1267345FF001256AD34DA23666B00B512309";
	uint8_t *b = malloc(20);
	int len = osmo_hexparse(str, b, 20);

	while (len--) printf("%02X", *b++);
	putchar('\n');
	return 0;
}

УМВР.

mix_mix ★★★★★
()
Последнее исправление: mix_mix (всего исправлений: 1)

i>>1

Зачем?! i/2 читается сильно лучше, а работает так же или быстрее.

По теме - дай минимальный пример программы с этой функцией, которую можно у себя скомпилить и запустить, чтобы понаблюдать эффект. Может быть, пока готовишь такой пример, разберешься, что ты делаешь не так.

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

Аргументом в функцию она передается.

LIKAN ★★★
() автор топика
Ответ на: комментарий от grondek
int gsm340_append_tpdu(struct msgb *msg){
	uint8_t *smsp;
	smsp = msgb_put(msg, 21);
	//char tpdu[] = {0x01,0x00,0x0B,0x91,0x97,0x51,0x30,0x38,0x23,0xF7,0x00,0x00,0x07,0xF4,0xF2,0x9C,0x9E,0x76,0x9F,0x01};
	char *tpdu;
	size_t tpdu_length;
	sock_server(&tpdu,&tpdu_length);
	uint8_t *b = malloc(20);
	
	int ret = osmo_hexparse(tpdu,b,20);
	printf("ret %d\n",ret);
	//FILE * logfile;
	//logfile=fopen("~/pdulog","w+");
	int i;
	printf("Before cycle\n");
	while (ret--) printf("%02X, ", *b++);
	printf("\n");
	memcpy(smsp,b,20 );
	free(tpdu);
	free(b);
	return tpdu_length;
} 

Я немного соврал, к памяти обращение идет весьма успешно. Правда ранее я пытался обращаться по индексам, т е в цикле b. Так вот, сейчас сегфолиться при освобождении памяти, вот что я вижу при работе программы. Падение происходит при вызове функции free

ret 20
Before cycle
01, 00, 0B, 91, 97, 51, 30, 38, 23, F7, 00, 00, 07, F4, F2, 9C, 9E, 76, 9F, 01, 
*** Error in `./mobile': free(): invalid next size (fast): 0x00000000022abe10 ***
======= Backtrace: =========
/usr/lib/libc.so.6(+0x73f8e)[0x7f3266f9af8e]
/usr/lib/libc.so.6(+0x7988e)[0x7f3266fa088e]
/usr/lib/libc.so.6(+0x7a04b)[0x7f3266fa104b]
./mobile[0x412f4b]
./mobile[0x413156]
./mobile[0x4347c4]
/usr/local/lib/libosmovty.so.0(+0x68a5)[0x7f326770b8a5]
/usr/local/lib/libosmovty.so.0(cmd_execute_command+0xce)[0x7f326770e3fe]
/usr/local/lib/libosmovty.so.0(vty_read+0x719)[0x7f3267710459]
/usr/local/lib/libosmovty.so.0(+0xcc71)[0x7f3267711c71]
/usr/local/lib/libosmocore.so.4(osmo_select_main+0x1d1)[0x7f3267921871]
./mobile[0x40477f]
/usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f3266f47000]
./mobile[0x4048ec]


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

А почему вы выделенную память не освобождаете, у меня сейчас как раз падение при вызове free.

LIKAN ★★★
() автор топика

Лучше бы завел структуру, в которой хранился бы и массив, и его размер. Тогда не было бы косяков, связанных с неправильным указанием размера массива.

l&1

а это нафига?

Ну и как-то ты переусердствовал что ли.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от E

Блин, а ведь правда, сейчас проверил. За 10 лет, оказывается, многое изменилось в оптимизации.

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

b выделяется явно в коде который приведен выше, f tpdu в ф-ции sock_server(&tpdu,&tpdu_length);

LIKAN ★★★
() автор топика
Ответ на: комментарий от Gvidon
nt  sock_server(char **tpdu, size_t *data_length){
  struct sockaddr_un srvr_name, rcvr_name;
  unlink(SOCK_NAME);
  int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
  if (sock < 0) 
  {
    perror("socket failed");
    return -1;
  }

  srvr_name.sun_family = AF_UNIX;
  strcpy(srvr_name.sun_path, SOCK_NAME);
  printf("binding %d\n",sock);
  
  if (bind(sock,(struct sockaddr *) &srvr_name, strlen(srvr_name.sun_path) +
        sizeof(srvr_name.sun_family)) < 0) 
  {
    perror("bind failed");
    return -1;
  }
  //Receiving tpdu
  *tpdu=Receiving_data(sock,rcvr_name,data_length);
  if(*tpdu == NULL){
    perror("Can't reseive pdu\n");
    return -1;
  }
  //sms_text[bytes]=0;
  close(sock);
  unlink(SOCK_NAME);
  return 0; 
}

char * Receiving_data(int sock, struct sockaddr_un rcvr_name, size_t *data_length ){
  socklen_t namelen;
  int bytes;
  //size_t data_length[1];
  bytes = recvfrom(sock, data_length, sizeof(size_t), 0, (struct sockaddr *)&rcvr_name, &namelen);
  printf("pdu_length=%d\n",*data_length);
  char *data=malloc(*data_length);
  bytes = recvfrom(sock, data, *data_length,  0,(struct sockaddr * ) &rcvr_name, &namelen);
  if (bytes < 0) 
  {
    perror("recvfrom failed");
    return NULL;
  }
  data[bytes]=0;
  printf("PDU %s\n", data);
  return data; 
}
LIKAN ★★★
() автор топика
Ответ на: комментарий от Eddy_Em

Честно говоря, функция osomo_hexparse входит в продукт, он не моя. И вызывается она много где. Её ковырять я не могу.

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

Любой из этих вызовов по отдельности вызывает сегфолт.

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

Для того, чтоб не было велосипедов. Зачем реализовывать то, что уже реализовано. Проблемы с вероятностью 99% не в функции.

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

uint8_t *b = malloc(20);

while (ret--) printf(«%02X, », *b++);

memcpy(smsp,b,20 );

Проблема тут. Дальше копай сам. Если не совсем дурак, то скоро дойдёт.

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

Так, окей, я понял. после цикла b++, b указывает на конец области памяти. Только вот беда free(tpdu) тоже падает, а с tpdu никаких инкрементов не производиться.

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

osmo_hexparse - без нареканий. Ошибка при работе с переменной «b»:

	uint8_t *b = malloc(20);
	int ret = osmo_hexparse(tpdu,b,20);
	while (ret--) printf("%02X, ", *b++); // теряешь указатель на веделенную память
	memcpy(smsp,b,20 ); // читаешь через не актуальный указатель
	free(b); // освобождаешь неизвестно что

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

valgrind на такие вопросы отвечает быстрее, чем лор.

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

char *data=malloc(*data_length);

sock_server(&tpdu,&tpdu_length);

Такой говнокод... Кто за тебя будет проверять возвращаемые функциями значения? Переходи на другой язык, С не для тебя.

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

Ага, только вот проблема в том, что return data. А в вышележащей ф-ции идет проверка, что возвращаемое значение не NULL. Зачем делать одну и ту же проверку дважды? tpdu так же не NULL, так как иначе osmo_hexparse не отработала бы корректно.

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

А почему вы выделенную память не освобождаете

Система освободит, лол. Ты не понял: проблема у тебя, в том как ты вызываешь функцию и что ты делаешь с памятью потом, а не в коде выше.

int main()
{
	const char *str = "45AF1267345FF001256AD34DA23666B00B512309";
	uint8_t *b = malloc(20);
	int i, len = osmo_hexparse(str, b, 20);

	for (i = 0; i < len; i++) printf("%02X", b[i]);
	return putchar('\n'), free(b), 0;
}

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

Вообще-то всегда быстрее всего были битовые операции, потом сложение/вычитание, потом умножение и только потом деление ЕМНИП. Сейчас наоборот разницы стало меньше.

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

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

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

Идиотизм какой-то. Введет человек 0xabc и лопухнется функция!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от LIKAN

free(tpdu) валится из-за переполнения буфера:

char * Receiving_data(int sock, struct sockaddr_un rcvr_name, size_t *data_length ){
...
  bytes = recvfrom(sock, data_length, sizeof(size_t), 0, (struct sockaddr *)&rcvr_name, &namelen);
  char *data=malloc(*data_length);
  bytes = recvfrom(sock, data, *data_length,  0,(struct sockaddr * ) &rcvr_name, &namelen);

  data[bytes]=0; // переполнение буфера

Такие ошибки valgrind ловит и очень подробно расписывает. Даже статический анализатор легко просекет. Освой модульное тестирование и инструментальные средства отладки. Хотя, да, согласен, что valgrind для ленивых трусов и чайников, а статический анализатор для красноглазых зануд в степени Пи. Но зато они тычут тебя носом в твое дерьмо уже на нулевом этапе разработки, что сводит затраты проекта до возможного минимума.

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

Спасибо конечно, но я ж ещё вчера отметил тему как решенную.

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