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

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

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

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 21.10.2011, 18:32   #1
Alessus
 
Регистрация: 21.10.2011
Сообщений: 6
Восклицание Ошибка выделения памяти в классе строк, прошу помочь.

Доброго дня всем. Прошу помочь в следующей проблеме. Некоторое время назад начал реализовывать собственный класс строк (только в целях самообучения), и вроде бы все шло нормально, до тех пор, пока не появилась очень странная ошибка. Выражалась она в следующем:
- В IDE NetBeans 7.0.1 программа компилируется успешно (COMPILE SUCCESSFUL), но нормально выполниться не может (RUN FAILED без каких-либо сведений об ошибках).
- В DevCpp portable вся видимость проблемы заключается в том, что консоль просто мигает и исчезает (окно программы появляется, и тут же исчезает), причем это происходит, сколько бы задержек в конце не ставилось (я имею ввиду что-либо типа cin.get()).
- Только компилятор g++ под Ubuntu сказал что-то вразумительное: ошибка в файле malloc.h, т.е. в выделении памяти.
Есть две очень странных лично для меня вещи:
1. При отладке в NetBeans все выполняется успешно, и в конце функция возвращает реально тот результат, который нужен. Но при обычном запуске программы вылезает все тот же RUN FAILED.
2. Ошибки непостоянны. Стоит поменять содержимое строк в функции main() или вызовы каких-то еще функций, и ошибка либо исчезает, либо появляется снова.
Ошибка появляется в методах erase(), которые принимают шаблон (точнее - подстроку обрабатываемой строки), и возвращают булево значение - получилось\не получилось стереть. При этом изменяется сама строка в объекте this (стирается заданная в аргументе подстрока, если она найдена).
Так же иногда подобная ошибка появляется из-за употребления методов find (возвращает индекс заданного в аргументе шаблона, если он есть, и -1, если нет) или substring (принимает два аргумента - начальный и конечный индекс подстроки в строке this, и возвращает саму подстроку, ограниченную индексами в аргументах, от индекса начала до индекса конца включительно), но этой причины я вообще не могу понять. Сами по себе find и substring работают нормально.
Если будет нужно, я выложу вывод компилятора g++ о файле malloc.h (этот вывод представляет собой 4-5 строк текста, которые для меня ничего не означают).

Последний раз редактировалось Alessus; 21.10.2011 в 21:56.
Alessus вне форума Ответить с цитированием
Старый 21.10.2011, 18:35   #2
Alessus
 
Регистрация: 21.10.2011
Сообщений: 6
По умолчанию

Код метода erase, в котором возникает проблема:

Последний раз редактировалось Alessus; 21.10.2011 в 21:54.
Alessus вне форума Ответить с цитированием
Старый 21.10.2011, 18:36   #3
Alessus
 
Регистрация: 21.10.2011
Сообщений: 6
По умолчанию

Код:
bool KAAString::erase(KAAString& s)
{
    int i = 0;
    if(!s.value)
        return false;
    else
        if(!s.size)
            return false;
        else
            if(s.size>size)
                return false;    
    int ind = find(s.value);
    if(ind == -1)
        return false;
    char* erased = new char[size - s.size];
    for(i = 0;i<ind;i++)
    {
        erased[i] = value[i];
    }
    ind += strlen(s.value);
    int k = 0;
    if(!(ind>=size))
    {
        for(k = ind;k<size;k++)
        {
            erased[i] = value[k];
            i++;
        }
    }
    erased[i] = '\0';
    delete[] value;
    size = strlen(erased);
    value = new char[size+1];
    strncpy(value,erased,size+1);
    return true;
}
Файл kaastrtest.cpp (тестирующий файл с функцией main() для проверки правильности работы класса).
Код:
#include "kaastring.h"
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
    KAAString s("I can't feel @#$ my legs!");
    KAAString a("@#$ ");
    s.erase(a);
    cout << s << endl;    
}
К слову, если в main() использовать не erase() с объектом KAAString, а с char*, то все работает, но в char* erase() тоже возникают проблемы, просто при других ситуациях.
И забыл сказать, что MSVS 2010 вообще не хочет запускать программу из-за каких-то проблем с .h файлами. Я сейчас работаю в ней редко, поэтому на эту проблему вообще не обращал внимания.
В общем, попытался как можно более детально описать проблему, очень прошу помочь, ибо даже не знаю, в чем она может заключаться.

Последний раз редактировалось Alessus; 22.10.2011 в 13:50.
Alessus вне форума Ответить с цитированием
Старый 21.10.2011, 20:48   #4
Сыроежка
Форумчанин
 
Регистрация: 01.07.2011
Сообщений: 423
По умолчанию

Юноша, никто не будет разбираться в ваших многочисленных строчках кода! Уважайте участников форума! Локализуйте проблему, чтобы примерный код составлял не больше 30-50 строчек! Вставьте отладочную печать, чтобы по печати отладочных сообщений локализовать проблему.
Со мной можно встретиться на www.clipper.borda.ru
Сыроежка вне форума Ответить с цитированием
Старый 21.10.2011, 21:50   #5
Alessus
 
Регистрация: 21.10.2011
Сообщений: 6
По умолчанию

Я, вроде бы, делаю все, чтобы писать наиболее уважительно, потому что никого не хочу, не дай бог, обидеть. А весь код полностью выложил только потому, что обычно, если человек просит помочь и выкладывает только кусок кода, ему говорят, что без всего кода разобраться нельзя, поэтому для большего удобства людей, которые решат помочь, выложил сразу все. В том-то и дело, что ошибки появляются такие, что невозможно понять, в какой конкретно точке кода возникает ошибка. Я знаю только, что ошибка где-то в методе erase(). Я сокращу файл реализации класса только до него, но вполне возможно, что для того, чтобы понять, где ошибка, вполне может понадобиться и какая-то другая часть реализации. Удаляю все, кроме метода erase(). Если нужно будет что-либо еще - пожалуйста, скажите об этом сразу, я выложу.
К слову, я немного не понимаю, как можно отладить этот метод, не имея на руках кода всего класса, т.к. во-первых, метод erase() использует другой метод find(), и во-вторых принимает в качестве аргумента объект этого же класса. Да и какие отладочные сообщения могут помочь? Я ведь писал выше, что построчное выполнение проходит без всяких ошибок, тогда как обычный запуск программы проваливается.

Последний раз редактировалось Alessus; 21.10.2011 в 22:09.
Alessus вне форума Ответить с цитированием
Старый 22.10.2011, 01:01   #6
An1ka
C++,DirectX/OpenGL
Форумчанин
 
Регистрация: 09.01.2011
Сообщений: 422
По умолчанию

Вот, удаляет подстроку в строке один раз:
Код:
#include <iostream>
#include <string.h>

class KAAString
{
   size_t size;
   char* str;

public:
   KAAString() : size(), str(){}
   KAAString( const char* s) : size( strlen( s))
   {
      str = new char[size];
      strncpy( str, s, size);
   }
   const char* find_substr( const KAAString& s) const;
   bool erase( const KAAString& s);
   friend std::ostream& operator << ( std::ostream& os, const KAAString& s)
   {
      char *ss = new char [s.size+1];
      strncpy( ss, s.str, s.size+1);
      ss[s.size]= '\0';
      os << ss;
      delete[] ss;
      return os;
   }
};

const char* KAAString::find_substr( const KAAString& s) const
{
   char *first = str, *last = str + size;
   while ( first != last)
  {
    char *p1 = first, *p2 = s.str;
    while ( *p1++ == *p2++)
     if ( p2 == s.str + s.size) return first;
    ++first;
  }
  return last;
}
bool KAAString::erase( const KAAString& s)
{
   const char *er_first =find_substr( s);
   if ( er_first != str + size)
   {
      char *new_s = new char [ size - s.size];
      char *sfirst = new_s;
      for ( char *first = str; first != str + size; ++first)
         if ( first < er_first || first >= er_first + s.size)
            *sfirst++ = *first;

      delete [] str;
      size -= s.size;
      str = new_s;
      return true;
   }
   return false;
}

int main()
{
    KAAString s("I can't feel @#$ my legs!");
    KAAString a("@#$ ");
    s.erase(a);
    std::cout << s << std::endl;
   return 0;
}
http://liveworkspace.org/code/51e92a...ee51e8f8ce0ece
An1ka вне форума Ответить с цитированием
Старый 22.10.2011, 02:19   #7
Alessus
 
Регистрация: 21.10.2011
Сообщений: 6
По умолчанию

Благодарю, что ответили, но хотелось бы так же разобраться все-таки в ошибке своего класса. Я ведь пишу его для самообучения, поэтому хочется, чтобы программа работала. А после битья головой об стену из-за одной ошибки в течении нескольких дней никакие идеи в голову уже просто не приходят. Если нужно, я выложу код метода find(), и остальные, которые будут нужны. Еще раз спасибо, что согласились помочь.
Alessus вне форума Ответить с цитированием
Старый 22.10.2011, 06:12   #8
An1ka
C++,DirectX/OpenGL
Форумчанин
 
Регистрация: 09.01.2011
Сообщений: 422
По умолчанию

Зачем у вас постоянно вызывается strlen, тем более по коду видно, что в вашем классе есть поле size размера строки ?
И strcpy не копирует завершающий ноль, при обращении (тот же strlen) к такой строке будет выход за пределы массива и краш программы. Используйте strncpy (исходная строка должна содержать нуль-символ).
An1ka вне форума Ответить с цитированием
Старый 22.10.2011, 13:45   #9
Alessus
 
Регистрация: 21.10.2011
Сообщений: 6
По умолчанию

Избавился от strlen в пользу size везде, где можно. Это действительно была моя ошибка - этот метод делался по образцу идентичного метода, который я написал раньше - у него в аргументе был char*, потому так и получилось. Так же заменил strcpy на strncpy, но, увы, это не помогло. При отладке я видел, что завершающий ноль этой функцией тоже копируется (т.к. никакого мусора в value не было), поэтому ничего хорошего не произошло - программа все так же завершается "RUN FAILED" в NetBeans. Тут какая-то проблема в самих строках выделения памяти. Возможно, что-то непроинициализировано, когда было нужно. Но сколько я ни пытался понять, что, ничего не получалось.
Alessus вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
чем отличаеються эти функции выделения и освобождения памяти? TotKtoNado Общие вопросы Delphi 4 17.06.2011 03:16
Функции для выделения, перераспределения и освобождения памяти ArtGrek Общие вопросы Delphi 9 14.03.2011 03:08
Определение способа выделения памяти (c++) Александр Елис Помощь студентам 2 31.07.2010 20:28
Проблема выделения динамической памяти в С++ oxygen90 Помощь студентам 3 14.09.2009 21:47
Динамическая выделения памяти megavolt91 Общие вопросы C/C++ 1 25.05.2009 21:05