🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.programming
8 messages
8 total messages Started by Szyk Cech Sat, 09 Mar 2019 13:08
Dziwny wyciek zasobów
#215453
Author: Szyk Cech
Date: Sat, 09 Mar 2019 13:08
116 lines
5052 bytes
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.Linux.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.Linux.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
Re: Dziwny wyciek zasobów
#215454
Author: Szyk Cech
Date: Sat, 09 Mar 2019 13:09
1 lines
1064 bytes
Sorry ntg. miało iść na: pl.comp.os.linux.programowanie
Re: Dziwny wyciek zasobów
#215455
Author: Wojciech Muła
Date: Sun, 10 Mar 2019 20:38
15 lines
1914 bytes
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.
Re: Dziwny wyciek zasobów
#215456
Author: Szyk Cech
Date: Sat, 23 Mar 2019 13:37
8 lines
1373 bytes
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...
Re: Dziwny wyciek zasobów
#215457
Author: Wojciech Muła
Date: Sat, 23 Mar 2019 20:30
17 lines
2099 bytes
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_initialization

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.
Re: Dziwny wyciek zasobów
#215458
Author: Borneq
Date: Sat, 23 Mar 2019 20:49
20 lines
1877 bytes
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_initialization
> 
> 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?
Re: Dziwny wyciek zasobów
#215460
Author: Szyk Cech
Date: Sun, 24 Mar 2019 10:55
2 lines
1121 bytes
Problem dotyczył praw pliku: kopiowałem plik z uprawnieniami r--r--r-- i 
chciałem go otworzyć do pisania.
Re: Dziwny wyciek zasobów
#215459
Author: Wojciech Muła
Date: Mon, 25 Mar 2019 22:13
31 lines
2705 bytes
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_initialization
> > 
> > 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.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads