Linux.by
https://forum.linux.by/

C и возрашение указателя
https://forum.linux.by/viewtopic.php?f=6&t=7632
Страница 1 из 2

Автор:  Silos [ 13 май 2006, 20:21 ]
Заголовок сообщения:  C и возрашение указателя

Собственно есть C, gcc и этот код:
Код:
#include <stdlib>
#include <stdio>

void ss(char *tr)
{
     tr = (char *)malloc(50);
     tr = "aaaa!";
}

int main(int argc, char **argv)
{
     char *ptr;
     ss(ptr);
     printf("%s", ptr);
     return 0;
}


Проблема заключается в том, что память выделяется, но изменить эту память не получается - printf печатает что угодно, то только не строку "aaaa!".
Как решить эту проблему?
PS Смотрел дебагером в main адрес в ptr один, в ss другой, но когда возвращается обратно в main адрес в ptr остается прежним.

Автор:  xaep [ 14 май 2006, 02:50 ]
Заголовок сообщения: 

2Silos: у тебя в коде по крайней мере 2 ошибки. Во-первых, чтобы ss изменяла значение ptr в main, нужно его передавать не по значению, а по ссылке( void ss(char* &tr) ). А во-вторых, ты выделяешь память в ss и потом теряешь указатель на нее, соответственно не освобождаешь. ИМХО у тебя проблема в понимании способов передачи параметров, а также представления строк и работы с памятью в C.

Автор:  Silos [ 14 май 2006, 09:46 ]
Заголовок сообщения: 

Вообще C я никогда не учил. А сейчас понадобилось.
Вот методом проб и ошибок написал окло 70% программы, но из за незнания как передать по ссылке застопорился.
В данном случае память можно не освобождать, ибо прграмма тестовая и очень быстро завершается. А как известно после завершения OS сама освободит занаятую память.
Проблемы понимания у меня нету, есть только проблема незнания:)
Спасибо!

Автор:  exe [ 14 май 2006, 11:04 ]
Заголовок сообщения: 

Silos, Почитай хоть какую книжку по С.

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

Особенно код функции ss() страшен. Ты думал что

tr = "aaaa!";

занесет строку по адресу в tr? Это просто ужасная ошибка.

Автор:  red f0x [ 15 май 2006, 08:55 ]
Заголовок сообщения: 

1. Коль скоро ss(char *tr) изменяет указатель, то её аргумент должен быть двойным указателем: char** tr.
Передача аргумента должна выглядеть так: ss (&ptr);
2. tr = "aaaa!"; - а это вообще страх господень...
Это не паскаль. Такое присваивание изменяет адрес, "содержащийся в указателе", а не то, на что указывает указатель. Для операций со строками есть целая толпа функций str*(), mem*().

xaep,
В С++ допустим т.н. ссылочный тип - (char& tr), к-й недопустим в C. (Усли речь шла об это?) Если речь шла о нём, то объявление ss (char* &tr) выглядит как-то странно... :wink:

Автор:  Silos [ 20 май 2006, 21:07 ]
Заголовок сообщения: 

Спасибо за помощь, разобрался!

exe, вот часть кода и код main.c для тестирования:

main.c
Код:
#include <stdlib>
#include <stdio>
#include "s_math.h"

int main()
{
   const char *inte = "int(f(x^2)d(x/2))";
   char *f_x, *d_x;
   s_int_parse(inte, &f_x, &d_x);
   printf("f(x) = %s\nd(x) = %s\n", f_x, d_x);

   free((void *)d_x);
   free((void *)f_x);

   return 0;
}



s_math.h
Код:
#ifndef S_MATH_H
#define S_MATH_H

int s_int_parse(const char *s, char **f_x, char **d_x);

#endif



s_math.c
Код:
#include <stdlib>

#include "s_string.h"

int s_int_parse(const char *s, char **f_x, char **d_x)
{
   char *pinte = malloc(s_len(s) - 4);
   int rc = s_cut(s, pinte, 4, s_len(s));
   char *ff_x = malloc(rc - 2);
   char *dd_x = malloc(rc - 2);
   char *gap = ")d(";
   rc = s_break_two(pinte, ff_x, dd_x, gap, 1);
   *f_x = (char *)malloc(rc - 2);
   *d_x = (char *)malloc(s_len((char *)d_x) - 2);
   (void)s_cut(ff_x, *f_x, 2, rc);
   (void)s_cut(dd_x, *d_x, 2, s_len(dd_x));

   free((void *)dd_x);
   free((void *)ff_x);
   free((void *)pinte);

   return 0;
}



По моему, этот код легко читаем:)

Автор:  exe [ 20 май 2006, 21:51 ]
Заголовок сообщения: 

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

Можно пожужжать :-) ? Это не издевательство, не указание на незнание, а просто code review. Вдруг задумаешся...

1. Где комментарии?
2. На некоторых платформах #include <malloc> пригодится
3. malloc возвращает void *, не везде есть преобразование (char *).
4. char *gap = ")g("; не смотрится
и так далее.

А самое главное, запуск из-под valgrind что говорит?
Я вижу 5 malloc, 3 free. А что valgrind --tool=memcheck говорит?

Можешь все мои комменты выбросить далеко, если не применимы.

Автор:  Silos [ 20 май 2006, 23:27 ]
Заголовок сообщения: 

Код:
3. malloc возвращает void *, не везде есть преобразование (char *).

Тоесть для правильности работы "везде" необходимо писать (char *)malloc?

Код:
2. На некоторых платформах #include <malloc> пригодится

А как это определить, где необходимо, а где нет?

Цитата:
1. Где комментарии?

Все их дикое количество было вырезано, что бы сюда запостить.
Не постить же 20 kb кода?
Меня один раз kife попинал за отсутствие таковых, так теперь коментирую, все что могу забыть, или же может быть полезно знать другому:)

Цитата:
4. char *gap = ")g("; не смотрится

Тоесть?

Цитата:
А самое главное, запуск из-под valgrind что говорит?
Я вижу 5 malloc, 3 free. А что valgrind --tool=memcheck говорит?


Код:
[silos@asakura s_lib]$ valgrind test
==2790== Memcheck, a memory error detector.
==2790== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
==2790== Using LibVEX rev 1471, a library for dynamic binary translation.
==2790== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.
==2790== Using valgrind-3.1.0, a dynamic binary instrumentation framework.
==2790== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
==2790== For more details, rerun with: -v
==2790==
==2790==
==2790== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 1)
==2790== malloc/free: in use at exit: 0 bytes in 0 blocks.
==2790== malloc/free: 30 allocs, 30 frees, 1,981 bytes allocated.
==2790== For counts of detected errors, rerun with: -v
==2790== No malloc'd blocks -- no leaks are possible.
[silos@asakura s_lib]$ valgrind --tool=memcheck test
==2799== Memcheck, a memory error detector.
==2799== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
==2799== Using LibVEX rev 1471, a library for dynamic binary translation.
==2799== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.
==2799== Using valgrind-3.1.0, a dynamic binary instrumentation framework.
==2799== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
==2799== For more details, rerun with: -v
==2799==
==2799==
==2799== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 12 from 1)
==2799== malloc/free: in use at exit: 0 bytes in 0 blocks.
==2799== malloc/free: 30 allocs, 30 frees, 1,981 bytes allocated.
==2799== For counts of detected errors, rerun with: -v
==2799== No malloc'd blocks -- no leaks are possible.
[silos@asakura s_lib]$


Цитата:
Можешь все мои комменты выбросить далеко, если не применимы.

Тише... Что мне давно не хватало, так это code review.
Вообщем то это хорошо.
Чем больше code review, тем лучше код!
:D :D
Вообщем было бы очень хорошо, если бы вы могли продолжить, я б исходники выслал бы, или бы выложил:)

Автор:  red f0x [ 21 май 2006, 02:02 ]
Заголовок сообщения: 

exe, #include <malloc> ?
А откуда такое? malloc без .h как-то на С++ смахивает :D Или может имеется в виду #include <malloc> ? Нет, на самом деле, без иронии, интересно.

Silos, может я ошибаюсь, но мне кажется, что правила хорошего тона требуют, чтобы всё, что было захвачено, было и освобождено (когда оно уже не нужно). Т.е., другими словами, на каждый malloc() должен быть свой free().

Автор:  red f0x [ 21 май 2006, 02:10 ]
Заголовок сообщения: 

Рискну ответить сам себе по поводу первого... По непонятным причинам после malloc проглатывается точка h.....

Автор:  exe [ 21 май 2006, 11:12 ]
Заголовок сообщения: 

Вот и мой review накрылся :-) просто забыл .h

насчет везде (char *) - правило хорошего тона. С проглотит и не поморщится и без него.

char *gap используется один раз - либо выкинь, либо определи как
константу или #define вверху. Считается более читабельным.

Автор:  Silos [ 21 май 2006, 13:24 ]
Заголовок сообщения: 

red f0x, на каждый malloc свой free.
Просто это кусок кода.

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

Спасибо!

Автор:  exe [ 21 май 2006, 13:53 ]
Заголовок сообщения: 

red f0x, Ты прав насчет malloc()/free(), но посмотри не вывод
valgrind - нету потери памяти. Значит у него где-то free() запрятан
при вызове других функций.

Silos, Будь осторожен с такими передачами - сложно уследить
за всеми указателями.

Автор:  Silos [ 21 май 2006, 16:37 ]
Заголовок сообщения: 

exe, без осторожности и внимательности здесь никак.
Протестировал я свою программу valgrind'ом(это около 1000 строк) - утечек не было обнаружено. Это уже радует:)

Тут встал другой вопрос:
Необходимо сделать функцию наподобие printf() - зарание не известно сколько ей будет передано аргументов. Как реализовать?
Или же смотреть в сторону масивов указателей?

Автор:  exe [ 21 май 2006, 17:14 ]
Заголовок сообщения: 

#include <stdargs>

extern void trPrintf(int flag, char *fmtStr, ...);
void trPrintf(int flag, char *fmtStr, ...)
{
va_list argP;
int save_errno = errno;

va_start(argP, fmtStr);
vsprintf(msgBuf, fmtStr, argP);
va_end(argP);

if (trPrintFunction == (traceHandler) NULL)
fprintf(stderr, "%s\n", msgBuf);
else
(*trPrintFunction)(msgBuf);

errno = save_errno;
}

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/