LINUX.ORG.RU

Помогите найти утечку в куске кода

 


0

1
void AString::Expand(int newsize)
{
    if(newsize == 0) return;
    char* newbuffer = new char[newsize];
    memset(newbuffer,0,newsize);
    if(count > 0){
        memcpy(newbuffer, buffer, count);
        if(buffer) delete[] buffer;
        buffer = newbuffer;
    }else{
        buffer = newbuffer;
    }
    count = newsize;
    newbuffer = 0;
}

valgrind говорит что в строчке char* newbuffer = new char[newsize]; утекает 1 байт, не понимаю как, в деструкторе delete[] buffer;

Ответ на: комментарий от pozitiffcat

memcpy просто копирует байты, не меняя размер buffer же. Мб в этом дело? Ты всё равно удаляешь buffer с тем же размером, с которым он был выделен.

aptyp ★★★★
()
Ответ на: комментарий от wota

Ну это да:-)
ТС, ты вообще что хотел сделать? Видимо заменить buffer на больший. Тогда вначале удали старый, и выдели память заново.

aptyp ★★★★
()
Ответ на: комментарий от aptyp

char* newbuffer = new char[newsize]; завел новый memcpy(newbuffer, buffer, count); скопировал со старого delete[] buffer; удалил стрый что не так то?

pozitiffcat ★★★
() автор топика

А что именно valgrind говорит? М.б. дело в зыкрывающем строку нуле и надо делать

new char[newsize+1]
(это вообще то зависит от того, как Вы со строками работаете).

Кстати, не отслеживается ситуация когда count>newsize

AIv ★★★★★
()
Последнее исправление: AIv (всего исправлений: 1)

в строчке char* newbuffer = new char[newsize]; утекает 1 байт

Т.е. n раз вызывая Expand, утекает ровно n байт?

gag ★★★★★
()

[code=cpp]
#include <iostream>
#include <cstring>

using namespace std;

int main()
{
int newsize = 10;
int count = 5;
char *buffer = new char [count];

if(newsize == 0) return -1;
char* newbuffer = new char[newsize];
memset(newbuffer,0,newsize);
if(count > 0){
memcpy(newbuffer, buffer, count);
if(buffer) delete[] buffer;
buffer = newbuffer;
}else{
buffer = newbuffer;
}
count = newsize;
newbuffer = 0;

delete [] buffer;
}

[/code]

[code]
andrew tmp $ g++ main.cpp -g -Wall
andrew tmp $ valgrind ./a.out
[/code]

[code]
==17197== Memcheck, a memory error detector
==17197== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==17197== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==17197== Command: ./a.out
==17197==
==17197==
==17197== HEAP SUMMARY:
==17197== in use at exit: 0 bytes in 0 blocks
==17197== total heap usage: 2 allocs, 2 frees, 15 bytes allocated
==17197==
==17197== All heap blocks were freed — no leaks are possible
==17197==
==17197== For counts of detected and suppressed errors, rerun with: -v
==17197== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
[/code]

frozenix ★★★
()
Ответ на: комментарий от pozitiffcat

Так а что мешает использовать malloc вместо new?

xterro ★★★★★
()

А деструктор кстати точно вызывается? printf туда какой нить суньте.

AIv ★★★★★
()

из названия класса понятно, что дело идет со строками, а строки в C++ как и в C - нуль-терминированы!, поэтому тебе нужн newsize+1 выделять

TOXA ★★
()
Ответ на: комментарий от TOXA

Может у него максимальная длина строки count - 1 символ?

frozenix ★★★
()

а зачем переизобреть std::vector ?

Reset ★★★★★
()

> count

unresolved external symbol.

> buffer

unresolved external symbol.

arsi ★★★★★
()

прекрати иметь мозги себе и окружающим. Коли говнокодишь на плюсах, так юзай std::string или std::vector. valgrind может не всегда адекватно сообщать об утечках и один байт ещё не показатель оной. Утечка будет иметь место, если размер станет пропорционален кол-ву вызовов ф-ии.

mashina ★★★★★
()

> утекает 1 байт, не понимаю как

хз как там в new, но {c,m}alloc может выделить один байт, если его попросили выделить ноль байт (чтобы вернуть валидный уникальный указатель в любом случае).

arsi ★★★★★
()
Ответ на: комментарий от arsi

хз как там в new, но {c,m}alloc может выделить один байт, если его попросили выделить ноль байт (чтобы вернуть валидный уникальный указатель в любом случае).

glibc'сишный malloc() технически не может выделить меньше 8и байт. Но и valgrind считает утечки не по фактическому объёму выделенной памяти, а по значению аргумента в том же malloc(). Либо valgring врёт, либо кто-то дёрнул malloc(1) или его аналог.

mashina ★★★★★
()

Тред не читал, но:

1. Почему в else нет delete[] buffer? (кстати, проверка на NULL не нужна)

2. А что будет если count > newsize?

kulti ★★
()
Последнее исправление: kulti (всего исправлений: 1)
Ответ на: комментарий от pozitiffcat

Да? Ну, это от того, что такое count зависит. Я думал счетчик элементов в буфере, т.е. он вполне может быть и 0, а буфер будет существовать.

Я б эту всю махину из if/else сократил до:

    if(count > 0){
        memcpy(newbuffer, buffer, count);
    }
    delete[] buffer;
    buffer = newbuffer;

И над вторым моим вопросом задумайтесь, пока ногу не отстрелили.

kulti ★★
()
Последнее исправление: kulti (всего исправлений: 1)

нету у тебя утечек. продолжай велосипедить.

nanoolinux ★★★★
()
Ответ на: комментарий от dismal_faun

У std::basic_string<> деструктор невиртуальный. Очень не рекомендуется его экстендить.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от pozitiffcat

Покажите конструктор, деструктор и использование.

AIv ★★★★★
()

Используй умные указатели(тут вроде достаточно unique_ptr). Если религия не позволяет использовать стандартную библиотеку - напиши свой велосипед. Руками с памятью в С++ работают только под капотом всяческих умных указателей, аллокаторов и пр. В коде логики так не делают.

anonymous
()

А count==0 что Вам помешало сделать то же самое что и для count>0
С++ допускает выделение нулевого кол-ва памяти(но настаивает что обращаться по полученному указателю это UB) и полученный указатель будет валидный(т.е. его нужно освободить через delete[]). valgrind же вероятно видит что какраз этого у Вас и нету.
Как оказалось выше об это сказали. Да, у Вас count как флаг, но valgrind то не человек, не может/обязан страдать Вашей логикой.

FeyFre ★★★★
()

Еще у valgrind есть опция --track-origin, которая выдаст стек момента аллокации в момент потери указателя и опция --db-attach=yes, которая даст возможность подключить отладчик в этот момент.

anonymous
()
Ответ на: комментарий от pozitiffcat

Чего вдруг? Требование препода?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.