Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Утечка памяти


Автор: kleks 7.4.2006, 21:56
Вот только начал писать класс для работы с длинными числами, написал конструктор, который на вход принимает строку:
Код

BigInt::BigInt(char *str)
{
    nol=0;
    long i, j;
    int tCelLen, tDrobLen, s;
char* ZapyatPos=strchr (str, ',');
    s=strlen(str);
    if (ZapyatPos==NULL)
    {
        droblen=0;
        tDrobLen=0;
        zposition=-1;
    }
    else
    {
        tDrobLen=&str[s]-(ZapyatPos+1);
    }
    
        
    if (str[0]=='-')
    {
        if (ZapyatPos==NULL)
        {
            sign=-1;
            tCelLen=s-1;
        }
        else
        {
            sign=-1;
            tCelLen=ZapyatPos-str-1;
            zposition=tCelLen+1;
        }
    }
    else
    {
        if (ZapyatPos==NULL)
        {
            sign=1;
            tCelLen=s;
        }
        else
        {
            sign=1;
            tCelLen=ZapyatPos-str;
            zposition=tCelLen;
        }
    }
    
    if (tCelLen<0) tCelLen=0;
    if (tDrobLen<0) tDrobLen=0;

    
    cellen=tCelLen;
    cel= new unsigned char [cellen];
    memset(cel,0,cellen);
    
    droblen=tDrobLen;
    drob= new unsigned char[droblen];
    memset(drob,0,droblen);
    
    if (tCelLen>0 && tDrobLen>0)
    {
    
    if (sign==-1)
    {
        for (i=1; i<=tCelLen; i++) {cel[i-1]=str[i]; cel[i]='\0';}
        for (i=0, j=tCelLen+2; i<=tDrobLen-1, j<=s; i++, j++) {drob[i]=str[j];}
    }

    else  
    {
        for (i=0; i<=tCelLen-1; i++) {cel[i]=str[i]; cel[i+1]='\0';}
        for (i=0, j=tCelLen+1; i<=tDrobLen-1, j<=s; i++, j++) drob[i]=str[j];
    }
    
    cout<<cel;
    cout<<",";
    cout<<drob;
    }

    if (tCelLen==0 && tDrobLen>0)
    {
        if (sign==-1) for (i=0, j=2; i<=tDrobLen-1, j<=s; i++, j++) drob[i]=str[j];
        else for (i=0, j=1; i<=tDrobLen-1, j<=s; i++, j++) drob[i]=str[j];
        cout<<",";
        cout<<drob;
    }
    
    if (tCelLen>0 && tDrobLen<1)
    {
        if (sign==-1) for (i=0, j=1; i<=tCelLen, j<=s; i++, j++) {cel[i]=str[j]; cel[i+1]='\0';}
        else for (i=0; i<=s; i++) {cel[i]=str[i]; cel[i+1]='\0';}
        cout<<cel;
    }
    

}

Имеятся и деструктор:
Код

~BigInt()
    {
        delete [] cel;
        delete [] drob;
    }

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

Автор: nikitao 7.4.2006, 22:31
kleks, какая ошибка?приведи весь класс целиком.Могу лишь предположить ,что класс деструктор удаляет невыделенную память,иными словами он должен выглядить так :
Код

~BigInt()    
    {    
       if(cel)
          delete [] cel;    
       if (drop)
          delete [] drob;    
    }

Автор: kleks 7.4.2006, 23:09
Цитата
приведи весь класс целиком

Код

class BigInt
{
private:
    unsigned char *cel;
    unsigned char *drob;
    int cellen;
    int droblen;
    int sign;
    int zposition;
    unsigned char nol;
public:
    ~BigInt()
    {
        if (cel)
            delete [] cel;
        if (drob)
            delete [] drob;
    }
    BigInt(char *str);
};

/************************************************************************************************/

BigInt::BigInt(char *str)
{
    nol=0;
    long i, j;
    int tCelLen, tDrobLen, s;
char* ZapyatPos=strchr (str, ',');
    s=strlen(str);
    if (ZapyatPos==NULL)
    {
        droblen=0;
        tDrobLen=0;
        zposition=-1;
    }
    else
    {
        tDrobLen=&str[s]-(ZapyatPos+1);
    }
    
        
    if (str[0]=='-')
    {
        if (ZapyatPos==NULL)
        {
            sign=-1;
            tCelLen=s-1;
        }
        else
        {
            sign=-1;
            tCelLen=ZapyatPos-str-1;
            zposition=tCelLen+1;
        }
    }
    else
    {
        if (ZapyatPos==NULL)
        {
            sign=1;
            tCelLen=s;
        }
        else
        {
            sign=1;
            tCelLen=ZapyatPos-str;
            zposition=tCelLen;
        }
    }
    
    if (tCelLen<0) tCelLen=0;
    if (tDrobLen<0) tDrobLen=0;

    
    cellen=tCelLen;
    cel= new unsigned char [cellen];
    memset(cel,0,cellen);
    
    droblen=tDrobLen;
    drob= new unsigned char[droblen];
    memset(drob,0,droblen);
    
    if (tCelLen>0 && tDrobLen>0)
    {
    
    if (sign==-1)
    {
        for (i=1; i<=tCelLen; i++) {cel[i-1]=str[i]; cel[i]='\0';}
        for (i=0, j=tCelLen+2; i<=tDrobLen-1, j<=s; i++, j++) {drob[i]=str[j];}
    }

    else  
    {
        for (i=0; i<=tCelLen-1; i++) {cel[i]=str[i]; cel[i+1]='\0';}
        for (i=0, j=tCelLen+1; i<=tDrobLen-1, j<=s; i++, j++) drob[i]=str[j];
    }
    
    cout<<cel;
    cout<<",";
    cout<<drob;
    }

    if (tCelLen==0 && tDrobLen>0)
    {
        if (sign==-1) for (i=0, j=2; i<=tDrobLen-1, j<=s; i++, j++) drob[i]=str[j];
        else for (i=0, j=1; i<=tDrobLen-1, j<=s; i++, j++) drob[i]=str[j];
        cout<<",";
        cout<<drob;
    }
    
    if (tCelLen>0 && tDrobLen<1)
    {
        if (sign==-1) for (i=0, j=1; i<=tCelLen, j<=s; i++, j++) {cel[i]=str[j]; cel[i+1]='\0';}
        else for (i=0; i<=s; i++) {cel[i]=str[i]; cel[i+1]='\0';}
        cout<<cel;
    }
    

}

А ошибка следующая: HEAP CORRUPTIPN DETECTED: after Normal block (#62) at 0x003327d8 CRT
detected that the application wrote to memory after end of heap buffer

Автор: maxim1000 7.4.2006, 23:35
Цитата(nikitao @ 7.4.2006, 21:31 Найти цитируемый пост)
if(cel)
          delete [] cel

с точки зрения стандарта удаление 0-вого указателя - обычное дело, и не приводит ни к каким проблемам
MSVC этому соответствует, BC++Builder, по-моему, тоже (не помню точно, но вроде проверял)

Автор: Daevaorn 8.4.2006, 09:13
kleks,
У тебя в классе BigInt есть два указателя, но нет конструктора копирования и оператора присваивания, что может повлечь за собой такие ошибки. Получается, что какой-то экземпляр класса пытается освободить указатель, который уже освобожден другим экземпляром.

Автор: MAKCim 8.4.2006, 09:31
а не проще так
Код

class BigInt
{
private:
    typeef vector<char> _Chars;
    bool minus_flag_;
    _Chars int_tail_, float_tail_;
public:
    class null_string {};

    BigInt(const char* number_)
    {
        assert<null_string>(number_);
        if (*number_==ct_minus)
        {
            minus_flag_=true;
            number_++;
        }
        else minus_flag_=false;
        while (*number_ && *number!=ct_devider) int_tail_.push_back(*number_++);
        if (*number) number++;
        while (*number_) float_tail_.push_back(*number++);
    }
};

Автор: kleks 8.4.2006, 22:16
Цитата

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

Тоесть написание:
Код

BigInt& operator=(const BigInt&);
BigInt (const BigInt& Copy);

должно помочь...попробую конечно, но разве,действительно, в этом проблема?!

Автор: MAKCim 9.4.2006, 09:11
Цитата

должно помочь...попробую конечно, но разве,действительно, в этом проблема?!

если идет работа с памятью напрямую (выделение и т д), и не переопределены конструктор копий и оператор присваивания, то да
не хочешь мучаться - используй vector, list ...(мой пример выше)

Автор: kleks 9.4.2006, 15:02
MAKCim,
Спасибо огромное, но всё таки хочется со своим примером разобраться, а отсюда такой вопрос:
Код

char *a="2342342";
memset (a,0,3);
.
.

Почему в таком виде ф-ия memset() не работает?!
И еще, ели есть строка видa char *a="324234234"; каким образом можно освободить память занимаемую этой строкой используя функция delete???
заранее благодарен...

Автор: MAKCim 9.4.2006, 16:04
Цитата

Почему в таком виде ф-ия memset() не работает?!

потому что a указывает на readonly строку (нельзя писАть)
память для не выделяется автоматически (сама строка находится в области константных данных)
освобождать эту память вручную не надо

Автор: kleks 9.4.2006, 23:36
У меня тут вопрос такого плана: может кто-нибудь писал класс для работы с длинными числами...или возможно где-то, можно скачать соответствующие библиотеки...подскажите пожалуйста?! smile

Автор: MAKCim 10.4.2006, 07:43
Цитата

У меня тут вопрос такого плана: может кто-нибудь писал класс для работы с длинными числами...или возможно где-то, можно скачать соответствующие библиотеки...подскажите пожалуйста?! smile

в нете полно
http://www.google.ru/search?hl=ru&q=%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0+%D1%81+%D0%B4%D0%BB%D0%B8%D0%BD%D0%BD%D1%8B%D0%BC%D0%B8+%D1%87%D0%B8%D1%81%D0%BB%D0%B0%D0%BC%D0%B8&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA+%D0%B2+Google&lr=

Автор: kleks 21.4.2006, 23:07
Лазил в интернете и как раз нашёл неплохой класс для работы с длинными числами smile Только вот воспользоваться им так и не получается - при компиляции выдаёт 3 каких-то непонятных ошибки (компилятор VS 6.0), ссылку найти так и не смог, поэтому выкладываю сам файл:
Код

// LNum.h: interface for the CLNum class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_LNUM_H__6C7DF4A7_515D_11D5_AC10_EBC1DD062A0B__INCLUDED_)
#define AFX_LNUM_H__6C7DF4A7_515D_11D5_AC10_EBC1DD062A0B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "string.h"
#include <iostream>
#define DefCelSize  10
#define DefDrobSize 10
#define DefTochnost 10
#define ITNUM 8
class CLNum  
{
ostream& operator<<(ostream& s,CLNum& a);
friend CLNum sqrt(CLNum& a);
//friend CLNum operator+(CLNum& a, CLNum& b);
//friend CLNum operator-(CLNum& a, CLNum& b);
public:
    CLNum();//пустой конструктор;
    CLNum(unsigned int ,unsigned int,int);//Целая и дробная части
    CLNum(long);//Получаем экземпляр класса из переменной типа long
    CLNum(char in);
    CLNum(char* in);
    CLNum(const int);
    CLNum& operator=(const CLNum&);
    CLNum(const CLNum& Copy);
    virtual ~CLNum();
    struct Error//это исключение, которое мы будем бросать при ошибках, например в конструктор передано значание строки "12ф32".
    {
        const char* p;
        Error(const char* q){p=q;}
    };
    struct DivZero//деление на ноль
    {
    };
    //операторы

    unsigned char& operator[](const int index);// возвращает элемент(цифру) данного числа. Цифры после запятой имеют отрицательный индекс.
                                               //[0]-первая после запятой цифра целой части
    bool operator==(CLNum& b);
    bool operator!=(CLNum& b);
    bool operator<(CLNum& b);
    bool operator<=(CLNum &b);
    bool operator>(CLNum& b);
    bool operator>=(CLNum& b);
    CLNum operator-();// Унарный минус
    CLNum& operator<<(const int count);//Сдвигаем влево на count знаков
    CLNum& operator>>(const int count);//Сдвигаем вправо на count знаков
    CLNum& operator+=(CLNum& b);
    CLNum& operator-=(CLNum& b);
    CLNum& operator*=(CLNum& b);
    CLNum& operator/=(CLNum& b);
    void TrimCel(); //Убирает слева ненужные нули. Освобождает память, занимаемую этими нулями
    void TrimDrob();//Убирает ненужные нули справа.
    int GetTochnost();
    void SetTochnost(const int a);
    int GetCellen(){return cellen;}
    int GetDroblen(){return droblen;}
    char GetSign(){return sign;}
    void SetVal(char* in);
    void SetVal(const int in);
private:
    unsigned char *cel;// Целая часть
    unsigned char *drob;//Дробная часть
    /*unsigned*/ int cellen;// Длина целой части длинного числа
    /*unsigned*/ int droblen;//Длина дробной части
//    int zposition;//позиция запятой
    char sign;//Знак числа
    unsigned char nol;//ссылку на этот элемент будет возвращаеть op[] если элемента с требуемым индексом не сущ.
    int tochnost;
};
ostream& operator<<(ostream& s,const CLNum& a);
CLNum operator+(CLNum& a, CLNum& b);
CLNum operator-(CLNum& a, CLNum& b);
CLNum operator+(const int a, CLNum& b);
CLNum operator*(CLNum& a, CLNum& b);
CLNum operator/(CLNum& a, CLNum& b); 
CLNum operator*(const int a,CLNum& b);
//CLNum sqrt(CLNum& a);
#endif // !defined(AFX_LNUM_H__6C7DF4A7_515D_11D5_AC10_EBC1DD062A0B__INCLUDED_)


Так выглядит h-файл..., cpp-файл вложен (хотел выложить сразу rar-файл, но форум выдавал ошибку smile ) 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)