C ++ выделение динамической памяти в функции - вопрос новичка - PullRequest
9 голосов
/ 19 декабря 2009

Я исследую утечку памяти, и из того, что я вижу, проблема выглядит следующим образом:

int main(){
    char *cp = 0;
    func(cp);
    //code
    delete[] cp;
}

void func(char *cp){
    cp = new char[100];
}

В комментарии к коду я ожидал, что cp будет указывать на выделенную память, но это все еще пустой указатель, означающий, что я никогда не удаляю память Что я делаю, wroing?

Ответы [ 7 ]

18 голосов
/ 19 декабря 2009

Вы присваиваете cp значение выделенной памяти. Тем не менее, это переменная в стеке: копия cp в main! cp локально для функции, в которой вы находитесь.

То, что вы хотите, это ссылка:

void func(char *& cp)

Это будет псевдоним cp для параметра, переданного в.

12 голосов
/ 19 декабря 2009
void func(char *cp){
    cp = new char[100];
}

В этой функции char * cp является « указателем , передаваемым copy », что означает, что они указывают на один и тот же адрес памяти, но не являются тот же указатель. Когда вы изменяете указатель внутри, заставляя его указывать куда-то еще, исходный указатель, который был передан, будет продолжать указывать на 0.

6 голосов
/ 19 декабря 2009

Параметр cp является локальной переменной функции - изменение его не меняет ничего вне функции. Лучший способ написать функцию:

char * func(){
    return new char[100];
}

И не делать напрямую с вашим вопросом, но вы, вероятно, должны использовать std :: string и std :: vector вместо динамически размещаемых массивов.

1 голос
/ 28 января 2016

Хотя ссылки замечательны тем, что предлагают интуитивную абстракцию, дополнительно улучшенную ссылочными значениями C ++ 11, позволяющими связывать функции (и другое эзотерическое кодирование), можно утверждать, что они обеспечивают какую-либо безопасность (а именно , почему это ссылка считается более безопасным, чем указатель ) Есть случаи, когда лучше решить вышеупомянутое указателем на аргумент функции указателя. В частности, когда необходимо поддерживать похожую кодовую базу в ANSI C и C ++.

#include <iostream>

using namespace std;

void func(char ** cp) {
    *cp = new char[100];
    //do something useful
    (*cp)[0] = 'A';
}

void func(char *& cp) {
    cp = new char[100];
    //do something useful
    cp[0] = 'B';
}

int main(int argc, char** argv) {
    char * cp;
    //pointer to pointer
    func(&cp);
    cout << "Index 0 : " << cp[0] << '\n' << flush;
    delete[] cp; //remember to delete!!
    //pointer to ref
    func(cp);
    cout << "Index 0: " << cp[0] << '\n' << flush;
    delete[] cp;
    return 0;
}

Конечно, удаление ресурсов памяти из-под действия инстагативной функции не подчиняется RAII.

1 голос
/ 19 декабря 2009

Функция только изменяет КОПИЮ на cp. Вместо этого используйте ссылку.

1 голос
/ 19 декабря 2009

Вы проходите в cbuf, а не cp.

0 голосов
/ 19 декабря 2009

Как уже упоминали GMan и Neil, чтобы работать, вам нужно изменить func на:

char* func();

или void func(char*& p);

, которая решит вашу непосредственную проблему.

Однако существует проблема с обслуживанием. В любом случае, func возвращает указатель. Что не ясно пользователю func, так это то, что возвращаемый указатель должен быть удален. По этой причине обычно избегайте этой конструкции, если не требуется 100%. Скорее всего:

  1. Помогите пользователю выделить правильный объем памяти, который затем может быть передан в func
  2. Использование объекта для хранения выделенной памяти. Затем объект может удалить массив символов при его разрушении.

Так что для кода C ++ я бы порекомендовал:


class CBuf
{
public
    CBuf() 
    {
        iBuf = new char[100];
    }
    ~CBuf
    {
        delete[] iBuf;
    }
    char* func()
    {
        //do stuff;
        return iBuf;
    }
private:
    char* iBuf;
};

int main()
    {
    CBuf cb;
    char* mychar = cb.func();
    //do stuff with character array

    //destructor gets called here because cb goes out of scope
    }

Однако, особенно в программировании на C, может быть на 100% необходимо иметь некоторую функцию сортировки для создания массива. Поэтому в C-программировании вы можете заменить деструктор функциями CreateCBuf и DestroyCBuf. Таким образом, пользователь вашей библиотеки будет знать, что возвращаемый буфер необходимо уничтожить.

...