2015-11-01 6 views
-2

Я почти закончил свой умный указатель (я знаю ...), поэтому я загрузил его на веб-сайт моего университета, который запускает несколько автоматических тестов моего кода. Есть две вещи неправильно с рядом тестов:Двойная свобода или коррупция, почему это появляется?

  • памяти или времени лимит превышен
  • проблемы доступа к памяти (т. Е нулевой указатель)

Дело в том, я не знаю, что какие-то тесты исключаются. Я могу читать стандартный вывод автоматизированных испытаний который я сделал, это написано:

In instantiation of ‘my_pointer<T>::my_pointer() [with T = tester]’: 
error: no matching function for call to ‘tester::tester()’ 
note: candidates are: 
tester::tester(my_pointer<tester>) 
candidate expects 1 argument, 0 provided 
tester::tester(const tester&) 
candidate expects 1 argument, 0 provided 

Так я предполагаю, что по какой-то причине он не будет ссылаться на мой my_pointer() конструктор? Это мой умный класс указателя:

template<class T> 
class my_pointer { 
    T* raw_pointer; 

public: 
    my_pointer() { 
     raw_pointer = new T(); 
     raw_pointer->incRefCnt(); 
    } 

    my_pointer(T *obj) : raw_pointer(obj) { 
     if(raw_pointer != NULL) raw_pointer->incRefCnt(); 
    } 

    my_pointer(const my_pointer<T>& smart_pointer) : raw_pointer(smart_pointer.raw_pointer) { 
     if(raw_pointer != NULL) raw_pointer->incRefCnt(); 
    } 

    T& operator*() { 
     return *raw_pointer; 
    } 

    T* operator->() { 
     return raw_pointer; 
    } 

    operator T*() { 
     return raw_pointer; 
    } 

    my_pointer<T> &operator=(const my_pointer<T> &smart_pointer) { 
     if(this != &smart_pointer && raw_pointer != NULL) { 
      /** if this was the last reference to the given memory address */ 
      if (raw_pointer->decRefCnt() == 0) { 
      delete raw_pointer;      
      } 

      raw_pointer = smart_pointer.raw_pointer; 
      raw_pointer->incRefCnt(); 
     } 

     return *this; 
    } 

    bool operator== (const T* pointer) { 
     return raw_pointer == pointer; 
    } 

    bool operator!= (const T* pointer) { 
     return raw_pointer != pointer; 
    } 

    bool operator== (const my_pointer<T> &smart_pointer) { 
     return raw_pointer == smart_pointer.raw_pointer; 
    } 

    bool operator!= (const my_pointer<T> &smart_pointer) { 
     return raw_pointer != smart_pointer.raw_pointer; 
    } 

    ~my_pointer() { 
     if(raw_pointer->decRefCnt() == 0 && raw_pointer != NULL) { 
      delete raw_pointer; 
     } 
    } 
}; 

Это класс, в котором ссылку можно пересчитать:

class refcounted { 
private: 
    int count; 
public: 
    refcounted() : count(0) { } 

    int incRefCnt() { 
     return ++count; 
    } 

    int decRefCnt() { 
     return --count; 
    } 
}; 

Вы можете увидеть какие-либо проблемы с кодом? Заранее спасибо!

+3

Это любопытный дизайн. Класс интеллектуального указателя может использоваться только с типами, которые наследуются от 'refcounted'? –

+4

Не хотите ли вы уменьшить счетчик ссылок в своем деструкторе и удалить, если это 0? – Kenney

+0

Также обратите внимание, что 'if (raw_pointer! = NULL)' избыточно. Таким образом, 'dest_pointer = NULL;' в деструкторе. –

ответ

3

Вы безоговорочно удаляете свой необработанный указатель в деструкторе. Это не верно. Вы должны уменьшить счетчик ссылок и только удалить, если он станет нулевым.

Вы также звоните raw_pointer->incRefCnt(); в нескольких местах без проверки, raw_pointer is NULL.

+0

Я сделал, как вы сказали, теперь это лучше. Но она по-прежнему дает мне ошибку для некоторых тестов: "проблема доступа к памяти (т. Е нулевой указатель)" – masm64

+0

О, и это стандартный вывод: chkpt # 1 конструкт 0 chkpt # 2 chkpt # 3 memberselect 0 chkpt # 4 chkpt # 5 chkpt # 6 – masm64

+0

Я что-то пропустил? Деструктор не делит счетчик ссылок. – Robinson

0

Я вижу две проблемы в вашем коде:

  1. В оператора =(): вы проверить if(raw_pointer != NULL) после того, как вы уже разыменовываются raw_pointer (на линии выше). Вы должны отменить проверки.

  2. В деструкторе: не следует ли сначала позвонить decRefCnt() и удалить raw_pointer, если счетчик ссылок упал до нуля?

Так как вам нужно практически один и тот же код в обоих operator=() и ~my_pointer() для уменьшения счетчика ссылок и удаление raw_pointer при необходимости (AFAICS), представляется более практичным, чтобы извлечь эту функциональность к новому способу и называют, что от обоих мест.

+0

Действительно ли это, чтобы вызвать деструктор из метод = перегрузка оператора? – masm64

+0

Кажется маловероятным, но я не уверен, действительно, я никогда не думал об этом. Но даже если это так, я не думаю, что это выглядит как чистый код. –