[ C / C++ ] — начинающим: задаем вопросы (архивная - 2015)

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by _Great_, 26 May 2007.

Thread Status:
Not open for further replies.
  1. groundhog

    groundhog Elder - Старейшина

    Joined:
    12 May 2007
    Messages:
    1,159
    Likes Received:
    425
    Reputations:
    180
    Указатель на тип char (один байт). Т.е. идентификатор такого типа содержит не данные, а указатель на область памяти где эти данные находятся.
     
  2. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    а в чем различие на практике?
     
  3. groundhog

    groundhog Elder - Старейшина

    Joined:
    12 May 2007
    Messages:
    1,159
    Likes Received:
    425
    Reputations:
    180
    То есть? Вопроса не понял...
     
  4. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    между типом со звездочкой и без звездочки. или без не бывает?
     
  5. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    В первом случае в переменной хранятся данные, во-втором адрес данных.
     
  6. groundhog

    groundhog Elder - Старейшина

    Joined:
    12 May 2007
    Messages:
    1,159
    Likes Received:
    425
    Reputations:
    180
    Piflit, звёздочка как раз и говорит о том, что данный идентификатор означает, что это не данные а указатель на реально место хранения данных. Пример:

    int *pint;
    int intvar = 10;

    На текущий момент pint не определён (содержит в себе неопределённый указатель), т.е. переменная pint которая связана с какой-то ячейкой памяти содержит в себе мусор, а переменная intval, которая связана с какой-то ячейкой памяти содержит целое число 10.

    pint = &intvar;

    Теперь pint содержит в ячейки памяти адрес по которому находятся данные из intvar;

    И если ты сделаешь printf("%d", *pint), то на экран выведется 10. Обрати внимание, чтобы получить значение, которое находится по указателю, нужно применить операцию разыменования (*).

    А вообще читай азы по сям...
     
    1 person likes this.
  7. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    Небольшое отступление к сообщению groundhog. Всегда определяйте указатели.
    int *pint = 0;
    Такие мелочи приводят к ошибкам в больших проектах, читайте книги.
     
    2 people like this.
  8. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    Всем спасибо, я разобрался.
    Я читал, но, видимо, не очень хорошо :rolleyes:
     
  9. KEZ

    KEZ Ненасытный школьник

    Joined:
    18 May 2005
    Messages:
    1,604
    Likes Received:
    754
    Reputations:
    397
    > а в чем различие на практике?

    Различие принципиальное. У тебя есть переменная scratch. Ее значение - это какие-то байты по адресу определенному. Когда ты к ней обращаешься
    char scratch = getColor( 0 );
    компиллер генерирует такой код, например:
    push 0
    call getColor // вызов getColor
    mov byte ptr [0x00401020], eax // положить результат в байт по адресу, тут ее адрес 00401020

    А предположим она у тебя char *scratch.
    Тогда она в 32-битной системе (проца) будет 4-байтным значением (DWORD, ULONG и тп), в ней будет хранится АДРЕС чего-то. Т.е. в принципе по*** пишешь ты char *scratch, void *scrach или int *scratch. Если указываешь звездочку - это значит там будет указатель 4-байтный. А тип - это значит на какой тип данных указывает переменная. Это надо чтоб компиллер тебе говорил об ошибках возможных. Впринципе можно взять указатель и рассматривать данные по нему как данные другого типа. Пример
    void *ptr = (void*)0x00401020; // указатель на 0x00401020
    ((mystruct*)ptr)->field1 = 0; // рассматриваем как указатель на структуру mystruct
    //или:
    *((int*)ptr) = 0; // рассматриваем *ptr (данные по адресу ptr) как int и кладем туда int
    тогда сначала берется значение по адресу какому-то (значение переменной), там лежит опять адрес, и значение по этому адресу уже будет *ptr.

    Если тебе, скажем, надо дать возможность ф-ии модифицировать переменную переданую (а не только передать ее значение) - можно передать указатель на нее. По этому адресу будет значение и ф-ия туда сможет записать свою ***ню.
    Или, скажем, у тебя какая-то структуру большая в памяти должна динамически выделяться, тогда делаем mystruct *s = (mystruct*)malloc( sizeof( mystruct ) );
    и у тебя в s указатель на место в памяти где отделено sizeof( mystruct ) байт под структуру. s->field1 - поле структуры. а если s хранит структуру а не указатель то s.field1.

    лол NiOx вроде умный чел а написал ***ню) нахер определять указатели ? че за правило неписаное такое?
    нихера не надо определять если явно не нужно.
     
    #209 KEZ, 31 Aug 2007
    Last edited: 31 Aug 2007
    4 people like this.
  10. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    Кез, ты не прав.
    Статическая память(секции .data, .bss) иницилизируется нулями при запуске программы. У переменных в стеке и куче гарантия такой инициализации отсутствует, поэтому нужно специально инициализировать такие переменные для нормальной работы приложения. Содержимое неинициализированной переменной неопределено, зато можно точно предсказать что будет содержаться в неинициализированной области памяти. Представь себе неинициализированною стековую переменную, в ней может оказаться куча всего, в том числе сохраненные регистры, переменные от предыдущих вызовов, и тд. Все зависит от нахождения такой переменной в стеке. Стоит лишь взять определенную область памяти под контроль и появится возможность эксплутации. Конечно программистам, которые пишут для себя калькуляторы и тд плевать на такие уязвимости, однако раньше в крупных opensource проектах можно было часто встретить такие баги, сейчас они почти не попадаются. Для наглядности приведу пример:
    Code:
    unsigned int func(char *s)
    {
    char *vuln;
    if(s)
    {
    vuln = malloc(1024);
    ...
    }
    free(vuln);
    return 0;
    }
    
    А теперь подумайте, если аргумент s будет равен нулю, то указатель vuln окажется неинициализированным до конца функции, где для него будет вызвана функция free. О результате подумайте сами.
     
    #210 Ni0x, 31 Aug 2007
    Last edited: 31 Aug 2007
    1 person likes this.
  11. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    То есть функция
    unsigned int func(char s)
    уязвимой тоже будет. так?
     
  12. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    Piflit, не совсем понял тебя.
    Если вызвать func(0), то функция free попытается освободить vuln, который будет содержать в себе "мусор", обычно программа просто аварийно завершится.
     
  13. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    я тоже чето не то написал.
    Code:
    unsigned int func(char *s)
    {
    char vuln;
    if(s)
    {
    vuln = malloc(1024);
    ...
    }
    free(vuln);
    return 0;
    }
    это уязвимым не будет. правильно?
     
    1 person likes this.
  14. AL Capone

    AL Capone Elder - Старейшина

    Joined:
    27 Mar 2007
    Messages:
    28
    Likes Received:
    29
    Reputations:
    5
    2Piflit если бы было так: char *vuln = NULL, то все номр. А в данном случае указатель не инициализированный. т.е это косяк в проге.
     
  15. Ni0x

    Ni0x Elder - Старейшина

    Joined:
    27 Aug 2006
    Messages:
    338
    Likes Received:
    157
    Reputations:
    37
    http://shellcode.ru/index.php?name=News&file=article&sid=14
    Указатели вовсе не обязательно иниицализировать, но новички всеже должны представлять, что существует класс уязвимостей, связанных с неинициализацией.
     
    #215 Ni0x, 31 Aug 2007
    Last edited: 1 Sep 2007
  16. z01b

    z01b Муджахид

    Joined:
    5 Jan 2007
    Messages:
    494
    Likes Received:
    382
    Reputations:
    22
    У меня Borland C++ Builder 6.0
    Я игрался в настройках, и теперь когда компилю прогу, то пашет она, только у меня (
    Как это исправить?
     
  17. GlOFF

    GlOFF Elder - Старейшина

    Joined:
    8 May 2006
    Messages:
    689
    Likes Received:
    484
    Reputations:
    4
    z01b В настройках проекта нужно отключить статические библиотеки, чтобы код входил уже в компилируемый файл -> В частности необходимо изменить настройки линкировки (linking) убрать галку -> "use dinamic RTL" . Если не поможет то ещё поищи что можно отключить :)
     
    1 person likes this.
  18. z01b

    z01b Муджахид

    Joined:
    5 Jan 2007
    Messages:
    494
    Likes Received:
    382
    Reputations:
    22
    Помогло, спс )
     
  19. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    что значит ошибка
    #include <winsock2.h> есть

     
    #219 Piflit, 2 Sep 2007
    Last edited: 2 Sep 2007
  20. NetMan

    NetMan Elder - Старейшина

    Joined:
    9 Feb 2004
    Messages:
    121
    Likes Received:
    37
    Reputations:
    34
    Piflit > Подключи winsock2.h перед windows.h
     
    2 people like this.
Thread Status:
Not open for further replies.