[Qt] Crash programu przy użyciu funkcji strcpy()

Siemka, otóż piszę sobie pewną aplikację w Qt , która pod wersją 5.0.1 przynajmniej w QtCreatorze chodziła bez problemów ale miałem problem z linkowaniem bibliotek aby uruchomić cokolwiek z pliku .exe a nie w builderze więc ściągnąłem sobie Qt 4.8.1 i problemy z linkowaniem minęły ale mam problem z pewną funkcją, która w owym Qt 4.8.1 wyświetla warningi, program się kompiluje ale po wywołaniu funkcji w trakcie działania programu się zawiesza.

Oto fragment kodu gdzie występuje warning:

void MainWindow::on_pushButton_clicked()

{

    char * cstr = new char [ui->lineEdit->text().length()];

        string costam;

        costam=ui->lineEdit->text().toStdString();

        strcpy(cstr, costam.c_str()); <--- trefna linijka

        int z;

        z=costam.length();

        for(int n=0;n
             string wynik;

             wynik=konwersja(cstr[n]);

             mors(wynik);

             Sleep(300);

            }

    delete[] cstr;

}

Log z kompilatora:

warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

Ma to zapewne jakiś związek z kompilatorem bo program działał poprawnie i w QtCreatorze i CodeBlocks(sam alogrytm) z MinGW a kompilując MSVC2010 się crashuje.

Napisy są zakończone bajtem zerowym (tzw. terminator), bufor musi być o 1 dłuższy od napisu, jeśli jest za krótki to nadpisujesz to co leży za nim i w zależności od tego, co tam się znajdowało, rezultaty mogą byc różne.

Nawet kompilator Cię ostrzega, że strcpy jest niebezpieczna przy niewłaściwym użyciu :wink:

A tak w ogóle to po co kopiujesz _std::string_a do cstringa? std::string też można indeksować [].

Jeśli chodziło Ci o takie coś:

char * cstr = new char [ui->lineEdit->text().length()+1];

to nie pomogło a kopiuje std::stringa do cstringa bo strcpy() jako drugi parametr nie przyjmie stringa tylko const char*.

Użyłem ogólnie całego tego zabiegu bo chcę później koniecznie iterować po tablicy znaków a to był mi jedyny znany sposób na osiągnięcie tego celu. Jeśli macie na to inny sposób to chętnie przyjmę ;p

:?: :?: :?: Metoda .c_str() _std::string_a zwraca const char* do przechowywanego tekstu i nawet używasz tego właśnie do skopiowania tekstu z _std::string_a do cstringa przy użyciu strcpy.

Używasz strcpy bo używasz strcpy? :?

A co jest nie tak z iterowaniem po _std::string_u?

Spróbuj może

string costam = ui->lineEdit->text().toStdString();

char* cstr = new char[costam.length() + 1];

strcpy(cstr, costam.c_str());

Albo:

string costam = ui->lineEdit->text().toStdString().c_str();

char* cstr = new char[sizeof(costam)]; // sizeof(costam) == strlen(costam) + 1

strcpy(cstr, costam);

Kto wie jaką magię przeprowadza length().

std::string przechowuje: wskaźnik do bufora, rozmiar bufora i długość tekstu w buforze (konkretne implementacje mogą się nieco różnić, jednak ogólnie tak to wygląda); sizeof poda rozmiar wyłącznie tych danych. Rozmiar _std::string_a nie zależy od długości tekstu (bo tekst jest przechowywany w oddzielnym fragmencie pamięci) i zależeć nie może bo rozmiary zmiennych muszą być określone w momencie kompilacji.

Zwraca długość tekstu zapisaną w obiekcie. Aby zapewnić kompatybilność z bibliotekami C, std::string umieszcza za tekstem terminator i jeśli ręcznie go nie nadpiszesz to wszystko będzie działać. Aby mieć wiekszą pewność można użyć str n cpy zamiast strcpy:

string costam = ui->lineEdit->text().toStdString();

char* cstr = new char[costam.length() + 1];

memset(cstr, 0, costam.length() + 1);

strncpy(cstr, costam.c_str(), costam.length());

Jednak nadal nie wiem dlaczego autor nie chce po prostu użyć samego _std::string_a :-s

No tak… I ja wykonuję sizeof na const char*, nie na std::string. :wink:

Z tym, że to też głupota bo to poda także po prostu wielkość wskaźnika. Popełniłem błąd, ale nie dokładnie tam gdzie piszesz. :wink: Sorki.

To co chciałem napisać powinno wyglądać:

string costam = ui->lineEdit->text().toStdString().c_str();

char* cstr = new char[strlen(costam) + 1];

strcpy(cstr, costam);

Chodziło mi o to, że być może length() + 1 zawiera mniej miejsca niż std::string.c_str() wymaga i dlatego pomyślałem by w obu przypadkach operować na cstringach (druga i trzecia linia). Jednak teraz widzę, że tak nie jest, dzięki i sorki. :slight_smile: