Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.05.2012, 17:14   #11
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

код, представленный 8Observer8, является небезопасным (не корректным), поскольку не содержит защиты от переполнения буфера.
_Bers вне форума Ответить с цитированием
Старый 26.05.2012, 17:38   #12
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,327
По умолчанию

Да не учёл, спасибо! Сейчас в коде как раз ситуация переполнения.

Код:
#include <iostream>
using namespace std;

int Fun(char* buf);

const int BSIZE = 3;

int main()
{
    char* stst = new char[BSIZE];

    if(Fun(stst) > 0) {
        cout << stst << endl;
    }
    else {
        cerr << "error: buffer overflow" << endl;
    }
 
    delete [] stst;
    return 0;
}

int Fun(char* buf)
{
    char stroka[] = "privet";

    if (sizeof(stroka) < sizeof(buf)) {
        strcpy(buf, stroka);
        return 1;
    }
    else {
        return -1;
    }
}
8Observer8 вне форума Ответить с цитированием
Старый 26.05.2012, 17:49   #13
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

2 уровня безопасности:
- перед вхождением в функцию (отрезать лишьнее, либо сгенерить ошибку)
- внутри функции (записать сколько можно, либо сгенерить ошибку)

код косячный

Последний раз редактировалось Stilet; 27.05.2012 в 10:34.
_Bers вне форума Ответить с цитированием
Старый 26.05.2012, 18:32   #14
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,327
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
код косячный
Чем он плох?

Цитата:
Сообщение от _Bers Посмотреть сообщение
2 уровня безопасности:
- перед вхождением в функцию (отрезать лишьнее, либо сгенерить ошибку)
- внутри функции (записать сколько можно, либо сгенерить ошибку)
Второе больше на правду похоже. Не встречал пока функцию для которой приходилось:
Цитата:
перед вхождением в функцию (отрезать лишьнее, либо сгенерить ошибку)
8Observer8 вне форума Ответить с цитированием
Старый 26.05.2012, 20:14   #15
Rififi
Старожил
 
Регистрация: 19.08.2009
Сообщений: 2,119
По умолчанию

Kaela

Обрати внимание на примеры от 8Observer8 - они крайне поучительны о том, как не надо писать программы... если, конечно, ты не хочешь быть уволенным за вредительство :lol:

Код:
#include <iostream>
using namespace std;

char* Fun();

const int BSIZE = 20;

int main()
{
    char* stst = new char[BSIZE];

    stst = Fun();
    cout << stst << endl;
 
    delete [] stst;
    return 0;
}

char* Fun()
{
    char stroka[] = "privet";

    return stroka;
}
имеем: утечку памяти, возврат адреса локальной переменно (порушенной на стеке), и кульминационный финал - крэш :D

Вот так работает:

... в стране "That never happens" :lol:

Код:
int Fun(char* buf)
{
    char stroka[] = "privet";

    if (sizeof(stroka) < sizeof(buf)) {
        strcpy(buf, stroka);
        return 1;
    }
    else {
        return -1;
    }
}
выражение sizeof(buf), к сожалению, делает вовсем не то, на что надеется 8Observer8 :D

правильный вариант:

Код:
#include <string>

std::string Fun()
{
    return "строка";
}
Rififi вне форума Ответить с цитированием
Старый 27.05.2012, 06:10   #16
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от 8Observer8 Посмотреть сообщение
Второе больше на правду похоже. Не встречал пока функцию для которой приходилось:
Я исхожу из мысли о том, что вызывающая сторона должна "подумать": что и куда она пихает.

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

И так на всех этажах.

Профит тут вот в чем: я запускаю игру в автоматическом режиме "невидимка". Игра полностью отыгрывается, как и положено. (причем она сама для себя на кнопки нажимает. Работает автоматика), только без графики. На экране ничего не видно. В таком режиме она может отыграть весь рабочий цикл игры за десятые/сотые/тысячные доли секунды.

В режиме отладки я запускаю её играть 10 000 игр, и иду пить чай.

Потом прихожу. Игра к этому моменту уже упала. по сути, система безопасности меня буквально ткнула носом в проблемную точку.

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

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

И вот, я запускал 10 000 автоматических игр, а крушение произошло на на 3700 какой нибудь игре.

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

Итого: мы получаем способ обнаружения редко-проявляющихся ошибок.
И экономим колоссальную кучу времени на отладке на всех этапах разработки продукта.
_Bers вне форума Ответить с цитированием
Старый 27.05.2012, 08:29   #17
rlib
Форумчанин
 
Аватар для rlib
 
Регистрация: 22.05.2012
Сообщений: 352
По умолчанию

[QUOTE=Kaela;1050862]
Цитата:
Сообщение от _Bers Посмотреть сообщение

тогда как мне реализовать возврат строки из функции?
если я не знаю, какая она будет, а хочу возвращать рандомную?
Обязан юзать динамическое выделение:
Код:
#include <string.h>
typedef char* string;
string alloc_mystring() {
  char *locstr = "My string"; 
  char *s = (string)malloc(strlen(locstr)+1);
  strcpy(s, locstr);
  return s;
}
void free_mystring(string s) {
  free(s);
}
rlib вне форума Ответить с цитированием
Старый 27.05.2012, 09:35   #18
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

[QUOTE=rlib;1051281]
Цитата:
Сообщение от Kaela Посмотреть сообщение

Обязан юзать динамическое выделение:
Код:
#include <string.h>
typedef char* string;
string alloc_mystring() {
  char *locstr = "My string"; 
  char *s = (string)malloc(strlen(locstr)+1);
  strcpy(s, locstr);
  return s;
}
void free_mystring(string s) {
  free(s);
}
Не обязан. Более того: в твоём варианте присутствует архитектурный фейл(!): нарушение инкапсуляции, нарушение инварианта и вызывающей, и вызываемой сторон.

В грамотной архитектуре тот, кто явно выделял память, тот должен явно и освобождать. Ты же процедуру выделения/удаления памяти размазываешь по всем участникам архитектурного сооружения, и вводишь путаницу: нефига не очевидно, кто должен следить за утечками памяти. Но что бы взаимодействовать, у тебя все участники должны учитывать особенности друг друга.
Этот анти-паттерн называют ещё "спаггети-код".


Вместо этого, можно сделать перегрузку функций, и единообразно принимать на входе вариантно или:
1. std::string переменную.
2. Массив чаров.
3. Указатель на чар, и размер буфера.

Компилятор без труда разберётся какую конкретно функцию нужно будет запустить для конкретного аргумента.

В первых двух случаях контроль за временем жизни строки сводится к ничего не деланью. В последнем случае, если вызывающая сторона явно выделяла память - она же её и будет удалять.
Но выделять память на куче вовсе не обязательно. С тем же успехом можно скормить и массив на стеке, + его размер.

Сама функция только загружает данные в переданный буфер, и больше ничего не делает.
_Bers вне форума Ответить с цитированием
Старый 27.05.2012, 16:25   #19
rlib
Форумчанин
 
Аватар для rlib
 
Регистрация: 22.05.2012
Сообщений: 352
По умолчанию

[QUOTE=_Bers;1051297]
Цитата:
Сообщение от rlib Посмотреть сообщение

Не обязан. Более того: в твоём варианте присутствует архитектурный фейл(!): нарушение инкапсуляции, нарушение инварианта и вызывающей, и вызываемой сторон.
Мы про C говорим, а не про C++. В C++ можно воспользоваться либо STL, либо самому класс для стрингов написать, т.е. вообще никаких проблем нет.
В любой ADT (Abstract Data Type) на C, функция create()_ создает динамический обьект и возвращает хендл user-у, котрый САМ обязан освободить этот обьект. Наверно, самым лучшим примером будет весь WinAPI.

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

Последний раз редактировалось rlib; 27.05.2012 в 16:34.
rlib вне форума Ответить с цитированием
Старый 27.05.2012, 17:24   #20
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,327
По умолчанию

Вспомним задание:

Цитата:
Сообщение от Kaela Посмотреть сообщение
тогда как мне реализовать возврат строки из функции?
если я не знаю, какая она будет, а хочу возвращать рандомную?
Функция возвращает строку, размер которой заранее неизвестен. Хорошим примером будет служить функция, которая читает строку из файла.

Мой вариант решения: это передавать в функцию указатель на буфер фиксированной длины и размер буфера. Функция getstr читает не более чем "размер буфера" (BSIZE-1). Остальное обрезается./

Код:
#include <stdio.h>
#include <string.h>

#define BSIZE 10

int getstr(char* buf, int lim);

int main()
{
    char buf[BSIZE];

    if (getstr(buf, BSIZE) > 0) {
        return 1;
    }

    printf("%s\n", buf);

    return 0;
}

// func: возвращает длину считанной строки а, в случае
// ошибки возвращает -1
int getstr(char* buf, int lim)
{
    FILE* fp;
    char* filename = "infile.txt";

    fp = fopen(filename, "r");

    if (fp == NULL) {
        fprintf(stderr, "error (in getstr): cannot open file \"%s\"\n", filename);
        return -1;
    }

    fgets(buf, lim, fp);

    fclose(fp);
    return strlen(buf);
}
8Observer8 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Возврат массива из функции max_prorok Помощь студентам 2 06.10.2011 12:39
Возврат 2 и более аргументов из функции. Drilla Microsoft Office Excel 2 18.09.2011 14:11
c++ возврат указателя из функции Neolit1819 Помощь студентам 6 28.03.2011 15:37
Мини бэйсик:объявление функции, вызов функции , возврат. AL_LORD Помощь студентам 2 14.10.2010 17:48
Возврат результата функции по ссылке gladov Общие вопросы C/C++ 2 24.06.2008 22:48