Programistyczne WTF jakie Was spotkały

Programistyczne WTF jakie Was spotkały
  • Rejestracja: dni
  • Ostatnio: dni
9

Dzieciak uczy się od miesiąca (!!!) języka niszowego, przeznaczonego do wąskiej dziedziny, nie zna żadnego innego języka - pisał podstawy w c++, czyli właściwie nic nie wie, a pisze na forum jak jakiś znawca :D

Gimnazjum, czy liceum?

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
0

Chciałem mieć pseudo element który będzie pod rodzicem. Wyczytałem sobie

An element with greater stack order is always in front of an element with a lower stack order.

Wytłumaczy mi ktoś dlaczego pierwszy przykład (1 is lower than 2) nie działa, ale drugi (-1 is lower than 2) już tak?

Kopiuj
        h1.fancy-shadow {
            position: relative;
            z-index:2;
            color: #10BD00;
        }
        h1.fancy-shadow:before {
            position: absolute;
            z-index: 1;
            font-size: 1.3em;
            font-family: "Vivaldi";
            opacity: 0.2;
            color: black;
            content: 'smth';
        }
Kopiuj
        h1.fancy-shadow {
            position: relative;
            z-index:2;
            color: #10BD00;
        }
        h1.fancy-shadow:before {
            position: absolute;
            z-index: -1;  /*  works :|  */
            font-size: 1.3em;
            font-family: "Vivaldi";
            opacity: 0.2;
            color: black;
            content: 'smth';
        }
hauleth
  • Rejestracja: dni
  • Ostatnio: dni
12

W związku z naszym spammeRem przeglądałem dokumentację i znalazłem takie coś:

ca31bba9b7.png

Co się wydarzyło w tym czerwcu-sierpniu? Lafix odkrył R, że pobrano bibliotekę 25000 razy?

satirev
  • Rejestracja: dni
  • Ostatnio: dni
5

Dzisiaj natrafiłem na pewien problem z rozpakowywaniem paczki szablonu zmiennoargumentowego, który jak dla mnie jest wtf. Szukałem i zastanawiałem się nad przyczyną takiego stanu rzeczy ale nie widzę racjonalnego wytłumaczenia dlaczego nie mogłoby to działać (zostać zaimplementowane). Tyle tytułem wstępu, teraz rzeczony wtf.

Przykładowo mamy, taki kod jak poniżej:

Kopiuj
template <typename... Args>
void foo(Args... args)
{
    [args...](){};   
}

int main()
{
    foo(4, 4.5f, "asdasdsa");
    return 0;
}

Super wszystko działa. Ale załóżmy teraz, że chcielibyśmy obsługiwać poprawnie r-value i l-value. No to nic prostszego, perfect frowarding i capture by forward panie!

Kopiuj
#include <utility>

template <typename... Args>
void foo(Args&&... args)
{
    [args = std::forward<Args>(args)...](){};   
}

int main()
{
    foo(4, 4.5f, "asdasdsa");
    return 0;
}

I co?
error: expected ',' or ']' in lambda capture list [args = std::forward<Args>(args)...](){};
Z jakiś przyczyn nie można zachować rozpakowanej paczki w zmiennej.

Workaround to zforwadowanie paczki do tuple:

Kopiuj
template <typename... Args>
void foo(Args&&... args)
{
    [args = std::std::forward_as_tuple<Args...>(std::forward<Args>(args)...)](){};   
}

Btw, trochę w tym temacie, a trochę poza - jeśli byłby ktoś zainteresowany to mogę skrobnąć artykuł na temat tego jak napisać fajny, generyczny singleton w C++ przy użyciu tag dispatchingu, tak by zachować lazy initialization + wymusić initialization, tak gdzie trzeba. Jak by znalazł się ktoś zainteresowany niech da znać via komentarz/PM.

AL
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1493
2

Workaround z GCC do MSVC 6 żeby namespace'y się zgadzały...

Kopiuj
	typedef ::size_t size_t2;
	#define size_t size_t2
ShookTea
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 629
5
winerfresh napisał(a):

W związku z naszym spammeRem

IMHO ostatnio nadużywa się słowa "spam". Przecież nie znaczy ono "flame" lub coś w tym guście (jak to się ostatnio używa), lecz natrętną reklamę.
Och, wait. Zwracam honor.

:P

  • Rejestracja: dni
  • Ostatnio: dni
10

Przyszła do nas aplikacja po testach penetracyjnych, do poprawy, bo oryginalna firma działająca 7 lat na rynku nie umiała poprawić banalnych SQLi i XSSów wykrytych w czasie audytu. Niektóre identyfikatory zmienione, zamysł kodu ten sam.

To jest diff kodu przed i po "poprawkach bezpieczeństwa". O samej jakości nie wspominam.

#1 - Escaping parametru przed sprawdzeniem, czy w ogóle istnieje - żeby nam ifa nie injectnęli...

Kopiuj
- 	if (empty($_GET['id'])) session_start();
+	 if (empty(neutralizeSQL($_GET['id']))) session_start();

#2 - Podmiana bezpiecznego kodu na niebezpieczny

Kopiuj
- 		$result = @mysql_query("SELECT * FROM tbl_firma_kategoria WHERE left_id='".intval($_GET['cat_id'])."'");
+	 	$result = $db->query("SELECT * FROM tbl_firma_kategoria WHERE left_id=".$_GET['cat_id']." LIMIT 1");

#3 - Cast na inta i escaping

Kopiuj
- 	$result2 = @mysql_query("SELECT * FROM tbl_firma_galeria WHERE user_id=".$firmaDane['user_id']);
+	 $result2 = $db->query("SELECT * FROM tbl_firma_galeria WHERE user_id=".neutralizeSQL(intval($firmaDane['user_id'])));

#4 - Zobaczył w dokumentacji operator trójargumentowy i zaczął nim szpanować w losowych miejscach, zamiast zrobić ifa

Kopiuj
		$redir = (isset($redir)) ? base64_decode($redir) : false;
		$redir = (!empty($redir) && check_url(CONFIG_SITE_URL.'/'.$redir)) ? $redir : false;

#5 - SQL injection w wyrażeniu bardzo poważna sprawa

Kopiuj
if (intval(neutralizeSQL($_GET['mode'])) == 1) {
   // ...
}

#6 - Tylko nie myślcie, że neutralizeSQL to jakaś sensowna funkcja
Neutralizacja HTML do zapytania SQL, szczena mi opadła do samej d**y.

Kopiuj
function neutralizeSQL($var, $kind='tekst') {
	global $db;

	$zmienna = htmlspecialchars(strip_tags($zmienna));

	switch ($rodzaj) {
		case 'numeric':
			return $db->real_escape_string(str_replace(' ', '', str_replace(',', '.', $zmienna)));
		break;
		case 'text':
			return $db->real_escape_string($zmienna);
		break;
	}
}

(mała poprawka na prośbę autora - msm, i dzek)

#7 - Hashowanie haseł
Oczywiście to substr($x, 0, 2) rozpieprzy hasha typu $2a$08$ albo $5$rounds=5000$.

Kopiuj
			$dbpasswd=$setinfo['usr_password'];
			$non_crypt_pass = $usr_password;
			$old_crypt_pass = crypt($usr_password,substr($dbpasswd,0,2));
			
			$new_pass = $uzytkownikClass->posol($usr_password);

Gdzie funkcja posol($x) to:

Kopiuj
	//posolenie hasła
	function posol($haslo) {
 
		#$salt = "4f4d34kjb7574sdoias1190ic3"; //przynajmniej 22 znaki

		#return crypt(md5($haslo), '$2a$10$'.$salt);

		return md5($haslo);

	}

Więc generalnie hasła hashowane czystym MD5 bez soli.

#8 - Register globals by design

Kopiuj
extract($_GET, EXTR_OVERWRITE);
extract($_POST, EXTR_OVERWRITE);
extract($_COOKIE, EXTR_OVERWRITE);

Nawet nie sądziłem, że coś takiego w stdlibie PHP w ogóle istnieje i ktoś może tego używać.
W którymś powyższym kodzie parametr $redir pochodził oczywiście bezpośrednio rozpakowany z $_GET. Problem zaczyna się, kiedy chcielibyśmy prześledzić skąd się dana zmienna wzięła. Tego czasem nie wiedzą sami developerzy:

Kopiuj
if($_COOKIE['foo'] == $foo) {
   // ...
}

#9 - Ciastko "uzytkownik"
Autoryzacja polega na wysłaniu użytkownikowi ciastka uzytkownik w składzie:

Kopiuj
id,login,hash_hasla_md5

Audyt oczywiście to wykazał i zalecenie było, żeby użyć losowego tokena, bo dowolny SQL injection umożliwiający na odczyt bazy umożliwia w banalny sposób craftowanie takich ciasteczek. Zalecenie oczywiście od góry do dołu olane.

Próbowaliśmy już to zrefaktoryzować i przenieść ciastko do wewnątrz sesji PHPowej - bo ona również jest startowana. Wykonanie niektórych akcji w systemie powodowało wylogowanie z dość enigmatycznego powodu. Po paru godzinach grzebania okazało się, że niektóre moduły robią np. coś takiego:

Kopiuj
$_SESSION = false;

#10 - Uwaga intruz
Jak komuś jeszcze nie wybuchł mózg to dobiję w ostatnim punkcie.

Kopiuj
	if (empty($_POST['aid']) OR empty($_POST['pwd'])) {
		$admintest=0;
		$alert = "<html>\n";
		$alert .= "<title>UWAGA INTRUZ!!!</title>\n";
		$alert .= "<body bgcolor=\"#FFFFFF\" text=\"#000000\">\n\n<br><br><br>\n\n";
		$alert .= "<center><img src=\"images/loading.gif\" border=\"0\"><br><br>\n";
		$alert .= "<font face=\"Verdana\" size=\"+4\"><b>Prosimy opuścić tą stronę!</b></font></center>\n";
		$alert .= "</body>\n";
		$alert .= "</html>\n";
		die($alert);
	}

Lepsze decyzje projektowe podejmowałem w gimnazjum. Przypominam, że firma która to zrobiła działa na rynku od 7 lat i ma się dobrze. Mam to poprawnie połatać. Nie wspomniałem jeszcze, że wejście na stronę główną generuje około 330 zapytań, niektóre lecą z pętli.

Jak nie dam znaku życia, to znaczy że utknąłem w ulubionym pubie. Over.

  • Rejestracja: dni
  • Ostatnio: dni
0

Przez kod od obsługi koszyka przewija się...

Kopiuj
$koszykClass->aktualizyjKoszyk(...);

Pierwszy raz w życiu stwierdzam, że ten kod to po prostu brute force. Jeszcze jeden fajny kawałek:

Kopiuj
function zrobCos($arg, $arg2) {
   // jakieś operacje na $arg i $arg2

   $arg = $_COOKIE['arg']; // totalnie zmieniamy kontekst, lol

   unset($arg); // na sam koniec funkcji unsetujemy zmienną - po co, czemu? :O
}

Czy ktoś tam umiał programować? Rozumiał koncepcję funkcji, pętli? To pytanie pozostaje otwarte.

  • Rejestracja: dni
  • Ostatnio: dni
2

Znaleźliśmy funkcję wołającą zapytania w pętli O(n) używaną w nestowanej pętli O(n^2).

To tłumaczy 330 zapytań po wejściu na stronę główną...

no_solution_found
  • Rejestracja: dni
  • Ostatnio: dni
0

@up to jeszcze nic. Ja przejąłem raz projekt CRM gdzie na podstronie było generowane 1000 zapytań, a na kolejnej prawie 2 tyś. A klient narzekał na słabą wydajność aplikacji :)

  • Rejestracja: dni
  • Ostatnio: dni
2

Helena, mam zawał.

kod.png

Riddle
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10227
0

Korzystam w javie z biblioteki która ma obrabiać obrazki. Nie jestem pewien czy tylko ta czy wszędzie tak jest, ale u mnie jeżeli mam czarno biały obraz, i ustawie całemu obrazowi png Transparency: 255. To mimo że nie ma tam nic widocznego, to i tak taka funkcja (która działa jak różdżka do wybierania kolorów) rozróżnia np rgba(255,255,255,0) i rgba(0,0,0,0).

Wydaje się logiczne, ale jednak przezroczysty to przezroczysty.

PS; Co dziwne, jeżeli wezmę kolor z jednego miejsca ("jasna" przezroczystość) i spróbuję wylać farbę na inne ("ciemna" przezroczystość) to wyjściowy plik jest taki sam (nawet sprawdziłem checksumy md5). Po wczytaniu sytuacja z funkcją-różdżką powtarza się.

NO
  • Rejestracja: dni
  • Ostatnio: dni
9

Na drugim semestrze informatyki miałem zastępstwo na programowaniu w C z jakimś doktorantem, proste programiki konsolowe, zalecał dawanie samych if. Zrobiłem operator wyrażenia trójargumentowy:

Kopiuj
zmienna = warunek ? wyrazenie1 : wyrazenie2;

Dziwił się, że tak można i się z tym jeszcze nie spotkał, ale skoro działa to chyba może być. Ech :)

`dodanie znaczników i ``` - @furious programming

dam1an
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
  • Postów: 1589
8

@up Ja zajęcia z podstaw Javy miałem z takim doktorem który chyba dość dawno nie napisał żadnego programu. Pokazywał nam slajdy z podstawami. Pętle, ify itp, jednocześnie je omawiając. Doszedł do wyrażenia trójargumentowego. Zatrzymał się na tym slajdzie. Czyta opis przez chwilę. W końcu mówi coś w stylu "A no to jest taki operator warunkowy dla zaawansowanych, tego nie będziemy używać"
Inna sytuacja, ten sam doktor. Każdy miał sobie wymyślić program który napisze na zaliczenie półroczne w Javie. Ktoś tam mówi że chciałby napisać klienta e-mail. Tłumaczy doktorowi jak to ma działać, że będzie można z programu odbierać pocztę, wysyłać maile itp. Doktor na to "Wysyłać? Nie bo to .. spam .. FBI .." Tu właśnie nie pamiętam, ale coś gadał o spamie, o FBI, CIA albo NSA że to się może im nie spodobać czy coś w tym stylu.
A z kolei inny wykładowca ciągle na .Net mówił kropka-net.
Ehh jeszcze tylko miesiąc tych studiów.

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

Ja zajęcia z podstaw Javy miałem [...] W końcu mówi coś w stylu "A no to jest taki operator warunkowy dla zaawansowanych, tego nie będziemy używać"

W sumie coś w tym jest, jednak jeśli to były zajęcia z podstaw programowania, to lepiej najpierw nauczyć się tworzenia zwykłych warunków, zanim zacznie się stosować skrócone wersje.

Olamagato
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Polska, Warszawa
  • Postów: 1066
3

@up Tylko, że to nie są żadne skrócone wersje, lecz wręcz odwrotnie. Wyłącznie dzięki temu operatorowi można w językach o składni C pisać wyrażenia funkcyjne, no i kod jest zwyczajnie czytelniejszy (ten dobrze napisany, z właściwymi nazwami funkcji/metod/zmiennych).
Naturalnym rozwinięciem tego podejścia do wyrażeń są wyrażenia łańcuchowe, które pozwalają zapisać kod programu w postaci funkcyjnej. Czyli to, co obecnie jest modne... :)

A to, że na polskich uczelniach zostają doktoranci bo są zbyt ciency, żeby pójść do dowolnej firmy, to tylko pokazuje, że na polskich uczelniach niczego nie można się nauczyć. W sumie to korzystne nawet bo płace rosną. :D

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

@Olamagato - to skrócone wersje warunków; Prosty przykład:

Kopiuj
if(intValue == 5)
  intResult = 4;
else
  intResult = 18;

niektórzy lubią też grupować pojedyncze wyrażenia klamrami:

Kopiuj
if(intValue == 5)
{
  intResult = 4;
}
else
{
  intResult = 18;
}

Powyższe można skrócić do czytelnego jednolinijkowca:

Kopiuj
intResult = intValue == 5 ? 4 : 18;

więc operator ten służy jak najbardziej do skracania kodu przy tak prostych warunkach; A nawet stwierdziłbym, że przydaje się on tylko i wyłącznie do przypisań, ewentualnie jeszcze do zwracania rezultatu funkcji;

Poza tym można spokojnie pisać kod, znając zwykły if, ale trójargumentowca nie; W drugą stronę to nie działa - często obsługuje się tylko jeden stan warunku (prawdę lub fałsz), czego operatorem trójargumentowym nie można zastąpić;

Wyłącznie dzięki temu operatorowi można w językach o składni C pisać wyrażenia funkcyjne

Nawet jeśli to prawda, to zauważ, że na zajęciach z podstaw programowania ludzie i tak nie mają pojęcia o tym, o czym się do nich mówi (chyba że ktoś wcześniej programował); Naturalne jest uczenie się stopniowo, od najbardziej podstawowych rzeczy, a zwykły warunek if jest elementem bardzo podstawowym; A jak już ogarnie się sens używania instrukcji warunkowych, to wtedy będzie można prezentować dodatkowe rzeczy na ich temat, w tym operator trójargumentowy.

Olamagato
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Polska, Warszawa
  • Postów: 1066
1

@up Polecam napisanie za pomocą samych ifów poniższej procedury (z kodu produkcyjnego):

Kopiuj
	private void moveFocusForward(boolean forward) {
		List<Node> nodes = queryPane.getChildren().stream()
			.filter(node -> node instanceof TextField).collect(Collectors.toList());

		Iterator<Node> it = nodes.iterator();
		for(Node previous = null, next; it.hasNext(); previous = next) {
			next = it.next();
			if(next.isFocused() && (forward ? it.hasNext() : previous != null)) {
				(forward ? it.next() : previous).requestFocus();
				return;
			}
		}
	}

Dla mnie brak możliwości użycia instrukcji wyrażeniowej, to w wielu wypadkach kompletnie nieczytelny kod (a to co widać, jest już i tak wystarczająco skomplikowane). Moim zdaniem nie da się takiego kodu napisać prościej i czytelniej nie tracąc nic z obecnej funkcjonalności. Ale może ktoś mnie zaskoczy? :)

Trebuh
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: okolice Łodzi
8

Trafne komunikaty to jak widać sprawa drugorzędna.
trafne_komunikaty.PNG

Koziołek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Stacktrace
  • Postów: 6822
1

Nowy projekt. No prawie nowy, bo klient podsyła nam to co spłodził jego dział IT za pomocą zip+email. Odpalamy Sonara

  • 48 plików
  • 55 klas
  • prawie 9k linii kodu...

Sonar wyliczył Technical Debt na 25 dni... 708 issues... w tym np coś takiego:

Kopiuj
if (dataSource == null) {
   synchronized (connectionJndiName) {
     //.... 
  }
}
fourfour
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 627
0

Może nie do końca programistycznie, ale... zachciało się przez Windows Update nowego .Net 4.5.2, jednak wciąż instalacja poprawki kończyła się błędem. Dziwnym jakimś, bo bez informacji w necie na jego temat. Pobrałem paczkę do instalacji wspomnianego frameworka, niecałe 70 MB. Uruchomiłem i.. już znam przyczynę, dla której był problem z instalacją...

user image

:)

  • Rejestracja: dni
  • Ostatnio: dni
0

Wiem, że to ani nowe, anie programistyczne, tylko analityczne, ale wtf jest:
Android używa MTP zamiast normalnego przesyłania danych do kompa.
Wszystkie pędraki, stary telefon, a nawet samochód mogę podmontować normalnie, ale już android który jest linuchem wybrał sobie jakiś standard ms.

Wizzie
  • Rejestracja: dni
  • Ostatnio: dni
8

JavaScript :D

Kopiuj
> '5' - 3
2 // weak typing + implicit conversions = headaches
> '5' + 3
'53' // Because we all love consistency
> '5' - '4'
1 // string - string = integer. what?
> '5' + + '5'
'55'
> 'foo' + +'foo'
'fooNaN' // Marvelous.
> '5' + - '2'
'5-2'
> '5' + - + - - + - - + + - + - + - + - - - '-2'
'52' // Apparently it's ok

> var x = 3;
> '5' + x - x
50
> '5' - x + x
5 // Because fuck math

zajumane z reddita

Trebuh
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: okolice Łodzi
0

Może nie programistyczne ale związane z Windowsem.
Ostatnio słyszałem więcej dźwięków z otwierającego się MessageBox'a z Windowsa, myślałem że to wirus. Skanowałem kilka razy, czyściłem rejestr i nic. Okazało się że w pewnej piosence występuje bardzo podobny dźwięk. Ciekawe kto zgadnie co to za piosenka ;)

somekind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
5

Dodawanie dat na stringach:

Kopiuj
int daysUntilExpriry = czytamy z bazy

string dateAsText = DateTime.Now.AddDays(daysUntilExpriry).ToString("yyyy-MM-dd") + "T23:59:59";
DateTime returnDate = DateTime.ParseExact(dateAsText, "yyyy-MM-ddTHH:mm:ss", null);

Ach, ten angielski profesjonalizm.

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

Przepisuję właśnie algorytm tokenizera formatowanego labelka, tyle że stosując inne podejście - zamiast kopiować fragmenty łańcucha do tokenów, po prostu zapamiętuję wskaźniki na początki i końce fragmentów sekcji (nagłówków lub paragrafów); Dzięki temu łańcuch kodu labelka będzie tylko jeden, a lista tokenów (czy tam ich macierz) będzie przechowywać pary pointerów;

Wszystko mam gotowe, testowy kod wygląda tak i pod FPC działa wyśmienicie; Ale jak zwykle Delphi7 się buntuje - ostatnia literka ostatniej sekcji to h, a ten skądś wytrzasnął d:

console.png

Na dodatek do procedury AddSection trafiają wskaźniki z poprawnymi znakami (sprawdziłem pod debugerem), a druga pętla nie zmienia parametru ALast - potem już tylko przypisanie i tyle; Dlaczego więc w procedurze ShowSectionsContent wskaźnik wskazuje na jakąś dziwną literkę? Zielonego pojęcia nie mam; Próbowałem tę ostatnią sekcję modyfikować i modyfikacje działają super, ale ta konkretna sprawia problemy...

Dziwne to, ale ważne że FPC robi to poprawnie.

szopenfx
  • Rejestracja: dni
  • Ostatnio: dni
0

Podczas dodawania AddSection masz

Kopiuj
AFirst: 'third paragraaa"q'
ALast: 'a"q'

zmieniłem też tekst na poniższy ale to jest to samo:
SAMPLE_CODE = AnsiString('qfirst headerq"first paragraph"q"second paragraph"qsecond headerq"third paragraaa"q');

A jednak nie...

musisz zamienić

Kopiuj
  procedure ExtractSectionsText(ACode: AnsiString);

na:

Kopiuj
  procedure ExtractSectionsText(var ACode: AnsiString);

Działasz na tymczasowej kopii łańcucha w tej funkcji.

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0

@szopenfx - nawet jeśli bym działał na kopii, to ta kopia będzie dokładnie taka sama jak oryginał;

Ale czaję co źle zrobiłem - trzeba przekazać łańcuch przez referencję i nie będzie problemu... :] Normalnie operuję na polu klasy komponentu, więc parametry mi niepotrzebne, jednak przy przenoszeniu kodu zastąpiłem parametrem odwołanie do pola i tu wałek z kopią;

Tyle że nadal WTFem jest to, że tylko i wyłącznie taka wartość parametru daje niepoprawne wyjście - jeśli zmienię o jeden znak ciąg ze stałej, to wyjście będzie już poprawne; Próbowałem na różnych ciągach i różnych kompilatorach, no i tylko ten konkretny daje nieprawidłowe wyjście (tylko w D7);

Czas chyba w końcu iść spać o normalnej porze...

flowCRANE
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Tuchów
  • Postów: 12269
0
Krolik napisał(a)

No, jesli Delphi nie umie zoptymalizować dostępu za pośrednictwem indeksów, to faktycznie inaczej pewnie się nie da.

Umie takie rzeczy optymalizować, FPC tak samo (którym kompiluję kod);

Czyli nie jest to w takim razie WTF Twojego kodu, a projektu biblioteki / kompilatora, że wszystko na wskaźnikach wymusza (rodem z C)

Tzn. nie wszystko, a niektóre z używanych przeze mnie funkcji, które operują na łańcuchach kodowanych w UTF-8; Głównie chodzi o funkcję UTF8CharacterToUnicode, która przyjmuje wskaźnik na pierwszy bajt znaku; Jakoś szczególnie nie utrudnia to przetwarzania łańcuchów, wręcz przeciwnie;

Chodziło mi tylko o to, że wskaźniki są bardzo błędogenne; np. to kompilator nie zagawarantuje Ci, że AFirst i ALast wskazują na część tego samego stringa.

Kompilator gwarantuje mi, że wskaźniki będą wskazywać na istniejące znaki w istniejącym łańcuchu, pod warunkiem że po ustawieniu wskaźników nie zmodyfikuje zawartości łańcucha - ale to normalne i nie dotyczy jedynie wskaźników na znaki; Moim błędem było przekazanie łańcucha przez wartość, dzięki czemu otrzymywałem kopię łańcucha, wskaźniki ustawiałem na znaki w skopiowanym łańcuchu, a po wyjściu z procedury referencja do łańcucha zostawała utracona (normalne zachowanie); Czyli wskaźniki wskazywały na pozostałość po łańcuchu; Gdybym przekazał łańcuch przez referencję, to wszystko by grało;

Do tego bardzo łatwo popełnić właśnie różne dziwne błędy z zamazywaniem pamięci.

Jeśli myśli się podczas pisania kodu (co czasem niestety, ale zawodzi), to nic się nie podzieje; Tym razem podczas przenoszenia kodu z klasy do testowego programu, nie pomyślałem o poprawnym przekazaniu parametru, dlatego też wyszedł wielki WTF; A tu się okazuje, że wszystko przez głupie niedopatrzenie;


Do przetwarzania łańcuchów używam wskaźników, dlatego że poprawny kod wykorzystujący je, pozwala na napisanie bardzo szybkiego skrawka kodu; Oczywiście można posiłkować się funkcjami z biblioteki standardowej, takimi jak Pos, PosEx, Copy czy Delete, jednak wielokrotne ich użycie znacznie spowalnia algorytm, albowiem wykonują kupę zbędnych rzeczy;

Weźmy na przykład pierwszą (wewnętrzną) pętlę z mojego kodu - szuka ona otwierającego znacznika, pomijając inne znaki; Jest to jedna pętla, gdzie w argumentach sprawdza czy wskaźnik na znak jest mniejszy od adresu ostatniego znaku, następnie czy wskaźnik wskazuje na znak znacznika i jeśli nie - inkrementuje wskaźnik za pomocą Inc - krótko i efektywnie; A teraz weźmy pod lupę funkcję PosEx, która ma nam zastąpić naszą pętlę; Oczywiście ona także używa wskaźnika do przeszukiwania łańcucha, jednak wykonuje zbędne sprawdzanie długości łańcucha, traci czas na inicjowanie zmiennych lokalnych oraz wymusza skopiowanie dwóch łańcuchów (w parametrach przekazanych przez stałą), aby móc wykonać przeszukiwanie lokalnie; W rezultacie działa dwa razy dłużej od mojej pętli; Niestety, ale taka jest cena uniwersalizmu;

Niby tak prosta operacja trwa bardzo krótko, jednak wywołań tej funkcji w procesie rozdzielania kontentu na sekcje będzie dziesiątki - a to tylko podział na sekcje; Kolejny algorytm dzieli każdą sekcję na słowa, który de facto także robi to na podstawie własnej pętli i wskaźników; Jeśli w nim znów skorzystać z PosEx - znów tracimy czas; A w jednym labelku słów może być setki, więc ma to duże znaczenie; Niestety dzielenie kontentu na sekcje i słowa to dopiero 10% procesu tokenizowania; Następnie każdą sekcję trzeba podzielić na linie (mierzyć kolejne słowa), według bieżacego stylu fontu, potem wyznaczyć punkty, w których będą zaczynać się linie; W następnej kolejności trzeba przewalić wszystkie tokeny i wydobyć informacje o linkach - pobrać regiony, w których kursor ma się zmienić, a treść linku przemalować;

To chyba tyle - jak widać kupa kodu; Kod musi być efektywny, dlatego że wszystko co opisałem wyżej, wykonywane jest po pierwsze każdorazowo przy zmianie szerokości komponentu (np. przy rozciąganiu okna z zakotwiczoną do obu boków etykietą), a po drugie - kilkakrotnie przy stworzeniu komponentu; Gdyby kod był wolny - rozciąganie komponentu powodowałoby migotanie całości i nędzny efekt;

Tak więc używam wskaźników, aby maksymalnie jak tylko potrafię przyspieszyć kod (oczywiście jeśli jest to konieczne); Większość algorytmów z modułu TSInfoUtils (z mojej biblioteki do obsługi plików TreeStructInfo) pisałem używając wskaźników, zamiast instrukcji z RTL; To pozwoliło zoptymalizować kod procedur i funkcji nawet o 50%;

Kiedyś nie przepadałem za wskaźnikami, nawet uznawałem je za zbędne; Jednak jak już je poznałem to polubiłem od razu, dlatego że pozwalają na pisanie szybkiego kodu; A jak piszę jakiś kod, to sam od siebie wymagam, aby wycisnąć z niego jak najwięcej się da :]

Koziołek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Stacktrace
  • Postów: 6822
3
Kopiuj
if (!LOG.isDebugEnabled()) {
    return pjp.proceed();
}
long time = System.currentTimeMillis();
try {
    return pjp.proceed();
} finally {
    time = System.currentTimeMillis() - time;
    LOG.debug("{}[args:{}] executed in {}ms", pjp.getSignature(), pjp.getArgs(), time);
}

pomiar czasu... debug...cóż więcej można chcieć... (kod z bratniego wschodu).

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.