-
1. Data: 2019-03-09 14:08:00
Temat: Dziwny wyciek zasobów
Od: Szyk Cech <s...@s...pl>
Witam
[WSTĘP]
Mam program w C++ oparty na bibliotece Qt. Generalnie program jest
niezależny od systemu operacyjnego. Jednak z jakichś dziwnych względów
biblioteka Qt nie ma możliwości operowania na datach plików i katalogów.
Dlatego napisałem funkcję w oparciu o Api Linux-a realizującą kopiowanie
dat plików. Jest to przydatne podczas kopiowania.
[PROBLEM]
Mam jakiś wyciek zasobów. W pewnym momencie operacja fopen się nie udaje
(po całkiem sporej liczbie poprawnych operacji). Wg mnie wszystko
powinno grać, ale błąd występuje.
[KOD]
Oto kod mojej funkcji:
void gCopyFileAtributes(QString aSource, QString aDest)
{
if(!QFileInfo::exists(aSource))
NOTIFY_EXCEPTION(QObject::tr("Source file does not exists:
%1").arg(aSource), gLibraryId, eErrorCode::eFileSystemError);
if(!QFileInfo::exists(aDest))
NOTIFY_EXCEPTION(QObject::tr("Destination file does not exists:
%1").arg(aDest), gLibraryId, eErrorCode::eFileSystemError);
FILE* lSrc = fopen(aSource.toUtf8(), "r");
if(!lSrc)
NOTIFY_EXCEPTION(QObject::tr("fopen failed for file: %1:
%2").arg(aSource).arg(strerror(errno)), gLibraryId,
eErrorCode::eFileSystemError);
FILE* lDest = fopen(aDest.toUtf8(), "w");
if(!lDest)
{
fclose(lSrc);
NOTIFY_EXCEPTION(QObject::tr("fopen failed for file: %1:
%2").arg(aDest).arg(strerror(errno)), gLibraryId,
eErrorCode::eFileSystemError);
}
struct stat lStat;
if(fstat(fileno(lSrc),&lStat))
{
fclose(lSrc);
fclose(lDest);
NOTIFY_EXCEPTION(QObject::tr("fstat failed for file: %1:
%2").arg(aSource).arg(strerror(errno)), gLibraryId,
eErrorCode::eFileSystemError);
}
// Update to the same uid/gid
if(fchown(fileno(lDest), lStat.st_uid,lStat.st_gid))
{
fclose(lSrc);
fclose(lDest);
NOTIFY_EXCEPTION(QObject::tr("fchown failed:
%1").arg(strerror(errno)), gLibraryId, eErrorCode::eFileSystemError);
}
// Update the permissions
if(fchmod(fileno(lDest), lStat.st_mode))
{
fclose(lSrc);
fclose(lDest);
NOTIFY_EXCEPTION(QObject::tr("fchmod failed:
%1").arg(strerror(errno)), gLibraryId, eErrorCode::eFileSystemError);
}
// Change access time
timeval lTimes[2];
lTimes[0].tv_sec = lStat.st_atim.tv_sec;
quint32 lUsecA(static_cast<quint32>(lStat.st_atim.tv_nsec / 1000));
lTimes[0].tv_usec = lUsecA;
// Change modification time
lTimes[1].tv_sec = lStat.st_mtim.tv_sec;
quint32 lUsecM(static_cast<quint32>(lStat.st_mtim.tv_nsec / 1000));
lTimes[1].tv_usec = lUsecM;
if(futimes(fileno(lDest), lTimes))
{
fclose(lSrc);
fclose(lDest);
NOTIFY_EXCEPTION(QObject::tr("futimes failed:
%1").arg(strerror(errno)), gLibraryId, eErrorCode::eFileSystemError);
}
fclose(lSrc);
fclose(lDest);
}
[OPIS FUNCKCJI]
Jak widać wszystko tworzone jest na stosie z wyjątkiem 2 zmiennych lSrc
i lDest. Jednak one są zawsze zwalniane i po za tym wyjątki nie są
zgłaszane w trakcie wcześniejszej pracy.
[OPIS ZGŁASZANEGO BŁĘDU]
File: ../../../../Kopia3/Src/Libs/Common/Src/FileTools.Lin
ux.cpp, in
line: 26, in function: gCopyFileAtributes
Error code: 3, Error message: fopen failed for file:
/tmp/Kopia/!-dokumenty 2019-03-09 13-17-03/Programowanie/Qt/C++ GUI
Programming with Qt 4/qt-book/chap06/mdieditor/images/new.png: Brak dostępu
Exception occurs! Sender: Common.so, Error code: 3
Message:
File: ../../../../Kopia3/Src/Libs/Common/Src/FileTools.Lin
ux.cpp, in
line: 26, in function: gCopyFileAtributes
Error code: 3, Error message: fopen failed for file:
/tmp/Kopia/!-dokumenty 2019-03-09 13-17-03/Programowanie/Qt/C++ GUI
Programming with Qt 4/qt-book/chap06/mdieditor/images/new.png: Brak dostępu
Bug report has been sent...
Może ktoś doradzi jak prawidłowo powinna wyglądać ta funkcja?
dzięki i pozdro
Szyk Cech
-
2. Data: 2019-03-09 14:09:42
Temat: Re: Dziwny wyciek zasobów
Od: Szyk Cech <s...@s...pl>
Sorry ntg. miało iść na: pl.comp.os.linux.programowanie
-
3. Data: 2019-03-10 21:38:03
Temat: Re: Dziwny wyciek zasobów
Od: Wojciech Muła <w...@g...com>
On Saturday, March 9, 2019 at 2:08:03 PM UTC+1, Szyk Cech wrote:
> Może ktoś doradzi jak prawidłowo powinna wyglądać ta funkcja?
> dzięki i pozdro
Weź to jak człowiek trzymaj w unique_ptr z własnym deleterem,
to unikniesz wycieków (jeśli jakieś są, bo nie zauważyłem
w tym kodzie).
auto closefile = [](FILE* f){fclose(f);};
std::unique_ptr<FILE, decltype(closefile)> infile{fopen("path", "r"), closefile};
Wtedy przestajesz się martwić, czy i kiedy wołać fclose,
bo to zrobi za Ciebie destruktor unique_ptr.
w.
-
4. Data: 2019-03-23 14:37:49
Temat: Re: Dziwny wyciek zasobów
Od: Szyk Cech <s...@s...pl>
Dzięki!
Mam jedno pytanie:
> auto closefile = [](FILE* f){fclose(f);};
> std::unique_ptr<FILE, decltype(closefile)> infile{fopen("path", "r"), closefile};
Czemu w drugiej linii stosujesz nawiasy klamrowe?!? Przecież to nie jest
ani funkcja ani inicjalizacja tablicy...
-
5. Data: 2019-03-23 21:30:11
Temat: Re: Dziwny wyciek zasobów
Od: Wojciech Muła <w...@g...com>
On Saturday, March 23, 2019 at 2:37:53 PM UTC+1, Szyk Cech wrote:
> Dzięki!
> Mam jedno pytanie:
>
> > auto closefile = [](FILE* f){fclose(f);};
> > std::unique_ptr<FILE, decltype(closefile)> infile{fopen("path", "r"), closefile};
>
> Czemu w drugiej linii stosujesz nawiasy klamrowe?!? Przecież to nie jest
> ani funkcja ani inicjalizacja tablicy...
Od C++11 można, to się nazywa "uniform initialization":
https://en.wikipedia.org/wiki/C%2B%2B11#Uniform_init
ialization
W ogóle ten kod można jeszcze uprościć, dopiero sam niedawno się tego dowiedziałem.
Wystarczy jedna linijka, bez lambdy:
std::unique_ptr<FILE, int(*)(FILE*)> infile{fopen("path", "r"), fclose};
w.
-
6. Data: 2019-03-23 21:49:04
Temat: Re: Dziwny wyciek zasobów
Od: Borneq <b...@a...hidden.pl>
W dniu 23.03.2019 o 21:30, Wojciech Muła pisze:
> On Saturday, March 23, 2019 at 2:37:53 PM UTC+1, Szyk Cech wrote:
>> Dzięki!
>> Mam jedno pytanie:
>>
>>> auto closefile = [](FILE* f){fclose(f);};
>>> std::unique_ptr<FILE, decltype(closefile)> infile{fopen("path", "r"), closefile};
>>
>> Czemu w drugiej linii stosujesz nawiasy klamrowe?!? Przecież to nie jest
>> ani funkcja ani inicjalizacja tablicy...
>
> Od C++11 można, to się nazywa "uniform initialization":
https://en.wikipedia.org/wiki/C%2B%2B11#Uniform_init
ialization
>
> W ogóle ten kod można jeszcze uprościć, dopiero sam niedawno się tego dowiedziałem.
Wystarczy jedna linijka, bez lambdy:
>
> std::unique_ptr<FILE, int(*)(FILE*)> infile{fopen("path", "r"), fclose};
>
> w.
>
A nie lepszy kod mniej uproszczony a bardziej czytelny?
-
7. Data: 2019-03-24 11:55:51
Temat: Re: Dziwny wyciek zasobów
Od: Szyk Cech <s...@s...pl>
Problem dotyczył praw pliku: kopiowałem plik z uprawnieniami r--r--r-- i
chciałem go otworzyć do pisania.
-
8. Data: 2019-03-25 23:13:21
Temat: Re: Dziwny wyciek zasobów
Od: Wojciech Muła <w...@g...com>
On Saturday, March 23, 2019 at 9:49:03 PM UTC+1, Borneq wrote:
> W dniu 23.03.2019 o 21:30, Wojciech Muła pisze:
> > On Saturday, March 23, 2019 at 2:37:53 PM UTC+1, Szyk Cech wrote:
> >> Dzięki!
> >> Mam jedno pytanie:
> >>
> >>> auto closefile = [](FILE* f){fclose(f);};
> >>> std::unique_ptr<FILE, decltype(closefile)> infile{fopen("path", "r"),
closefile};
> >>
> >> Czemu w drugiej linii stosujesz nawiasy klamrowe?!? Przecież to nie jest
> >> ani funkcja ani inicjalizacja tablicy...
> >
> > Od C++11 można, to się nazywa "uniform initialization":
https://en.wikipedia.org/wiki/C%2B%2B11#Uniform_init
ialization
> >
> > W ogóle ten kod można jeszcze uprościć, dopiero sam niedawno się tego
dowiedziałem. Wystarczy jedna linijka, bez lambdy:
> >
> > std::unique_ptr<FILE, int(*)(FILE*)> infile{fopen("path", "r"), fclose};
> >
> > w.
> >
> A nie lepszy kod mniej uproszczony a bardziej czytelny?
Można jeszcze inaczej:
std::unique_ptr<FILE, decltype(&fclose)> infile{fopen("path", "r"), fclose};
Ale masz 100% rację, że to wciąż koślawy zapis. Chwilę mi zajęło,
zanim doszedłem do powyższego zapisu. Lambda najbardziej oczywista
i co więcej GCC ładnie ją inlinuje.
w.