Black Friday je tu! Využij jedinečnou příležitost a získej až 80 % znalostí navíc zdarma! Více zde
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Caster
Člen
Avatar
Caster:23. října 15:56

Při volání funkce předávám poslední parametr jako ukazatel na hodnotu délky pole. Z neznámých důvodů se ale po provedení funkce hodnota délky pole změní ze 16 na 20 a první 4 byty pole se přepíší jinými hodnotami.

Zkusil jsem: Na začátku programu definuji:

unsigned char digest16[16];
unsigned int  digest16_len = 16;
unsigned int* ptrdigest16_len = &digest16_len;
unsigned char PMKID[16];
unsigned char PMKID_Salt[20];

do pole PMKID pak uložím 16 bytů převedených z:

const char PMKID_str[] = "b0b606458a7945cf7c80b7fefe390506";

Chci docílit: Aby se po volání funkce nezměnila hodnota délky pole digest16_len a nepřepsaly se mi první 4 byty pole PMKID.

Tuším, že je problém asi v nesprávné definice ukazatelu na délku pole PMKID.

Vlastní volání funkcer vypadá takto, funkce vrátí správný výsledek do pole digest16:

HMAC(EVP_sha1(), (const char*)digest, 32, (const unsigned char*)PMKID_Salt, sizeof(PMKID_Salt), digest16, ptrdigest16_len);
 
Odpovědět
23. října 15:56
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:23. října 18:36

Nečteš dokumentaci. Je naprosto v pořádku že se hodnota proměnné přidané jako argument mění, neboť funkce vrací ukazatel na tuto proměnnou. Poslední parametr je totiž výstupní nikoli vstupní.

Jinak je zbytečné ukládat si velikost pole jehož rozměr znáš. Používej operátor preprocesoru sizeof.

Dále jsem si všiml že dost často nevytváříš vazby mezi velikostí pole a polem. Takovýto postup brzy povede k chybě v programu.

Nahoru Odpovědět
23. října 18:36
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:23. října 18:49

Stále mi nejsou moc jasné rozdíly v definici polí. Nicméně jsem problém vyřešil zadáním posledních dvou parametrů NULL, NULL (inspirovalo mě pár odkazů na použití funkce na Internetu) a přiřazení výsledku funkce do pole:

unsigned char* digest16 = NULL;
digest16 = HMAC(EVP_sha1(), (const char*)digest, 32, (const unsigned char*)PMKID_Salt, sizeof(PMKID_Salt), NULL, NULL);
 
Nahoru Odpovědět
23. října 18:49
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:23. října 19:15

Co konkrétně Ti na polích není jasné?

Nahoru Odpovědět
23. října 19:15
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:23. října 20:50

Přiřazování hodnot, například:

unsigned char digest[32];
const char MAC_AP[] = "c0c1c04bfc68";
char* password = { (char*)("MTRTogrt") };
 
Nahoru Odpovědět
23. října 20:50
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:23. října 21:28

Takže inicializace řetězců. Nic na tom není.

První případ je pole pro uložení 32 znaků nebo řetězce o délce 31 znaků (ukončeno nul znakem). Pokud je globální, obsahuje nuly, pokud je statické, obsahuje nuly, pokud je lokální, obsahuje odpad.

Druhý případ je pole obsahující řetězec který nelze měnit, protože const. Délku si umí spočítat překladač, je rovná počtu znaků + 1 nul znak. Funguje to tak že se vytvoří řetězec v rabulce řetězců, vytvoří se pole a zkopíruješ se řetězec do tohoto pole. Lépe je konstantní řetězec vytvořit takto:

char* str ="retezec";

Takovýto zápis je rychlejší neboť se řetězec vytvoří pouze v tabulce řetězců, a ty držíš pouze ukazatel na řetězec. Opět takovýto řetězec nelze měnit.

Pokud chceš měnit řetězec, musíš jej deklarovat jako pole:

#define SIZE 10
char str[SIZE];

Nebo vytvořit dynamicky:

char *str = NULL;

A pak použít malloc() nebo calloc() a nakonec uvolnit pomocí free().

Nelze deklarovat pole takto:

char str[];

Chybí rozměr.

Nahoru Odpovědět
23. října 21:28
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
DarkCoder
Člen
Avatar
DarkCoder:23. října 21:56

Dále když máš řetězec velké délky tak nechej délku na kompilátoru a nepočítej délku sám. Nikdy!

Když deklaruješ a inicializujes pole pro uložení řetězce takto:

char str[] = "test";

Tak str zabírá v paměti 5 bytů a lze uložit až 4 znaky.

Pokud takto:

char str[10] = "test";

tak str zabírá v paměti 10 bytů a lze uložit až 9 znaků. Ale lze změnit obsah třeba na "testuji" pomocí strcpy() protože se rám nový řetězec vejde. To u prvního případů nelze.

Nahoru Odpovědět
23. října 21:56
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:24. října 7:43

Nepřišel jsem na to jak rovnou převést string na pole:

test = random_string(8);
password = &test[0];

kde je definováno

string test;
char* password = NULL;
 
Nahoru Odpovědět
24. října 7:43
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:24. října 12:07

Je mnoho způsobů..

Máme-li řetězec:

string str = "muj retezec";

Pak pro konstantní řetězce:

const char* arr1 = str.c_str();

nebo

char* arr2 = &str[0];

Pro modifikovatelný řetězec:

char* arr3 = new char[str.length() + 1];
str.copy(arr3, str.length());
arr3[str.length()] = '\0';
Nahoru Odpovědět
24. října 12:07
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:24. října 19:30

Neví, jak to zadat na jednom řádku:

password = &random_string(8)[0];

Hlásí mi chybu:
C26815 Ukazatel je nepropojený, protože ukazuje na dočasnou instanci, která byla zničena

 
Nahoru Odpovědět
24. října 19:30
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:25. října 2:59

Jak chceš udržovat adresu objektu který si ani neuložíš?

Takto:

std::string str = random_string(8);
const char* password = str.c_str();
// const char* password = &str[0];

Nicméně toto není to co potřebuješ, to je určeno pro konstantní řetězce, ty potřebuješ pole modifikovat.

Navíc generování řetězců není správná cesta k dosažení toho čeho chceš dosáhnout. Je třeba postupovat systematicky, obsah pole měnit jasně daným způsobem. Tak jak fungují např. staré tachometry nebo mechanické elektroměry. Dále je třeba optimalizovat na rychlost. To znamená že jakákoli konverze nepřichází v úvahu. Zapomeň. Používej C-čkové řetězce a nepoužívej string z C++ které jsou sice pohodlné ale pomalé. Vytvářej si své vlastní funkce a nekopíruj kde co někdo napsal. Práci s polem budeš dělat prakticky pořád, takže dle toho vytvoř funkce. Zadávej co nejméně dat, vracej co nejméně dat. Neduplikuj. Ač je v 99% logické a správné tvořit funkce s parametry a vracet hodnoty, tak ty se musíš zamyslet a v některých případech to obejít. Podívej se např. na funkci random string(). Vrací řetězec, popř. referenci či ukazatel, má parametr. Takto tu funkci teď psát nebudeš. Funkce musí přebírat data zvenčí. Natahování argumentů a vrácení hodnot stojí procesorový čas, ty jej nemáš nazbyt.

Nakonec Ti doporučím zainvestovat více času do studia problematiky ukazatelů, budeš pak postupovat mnohem snáz a nebude to styl pokus omyl.

Nahoru Odpovědět
25. října 2:59
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:25. října 10:13

O rychlost mi samozřejmě jde. Zkouším upravit program z Internetu, který mi pod Linuxem & GPU běží rychlostí 2 bilióny hashí/s (SHA256) na Windows.

 
Nahoru Odpovědět
25. října 10:13
Avatar
Caster
Člen
Avatar
Caster:26. října 0:16

U funkce:

void hostRandomGen(unsigned long* x) {
    *x ^= (*x << 21);
    *x ^= (*x >> 35);
    *x ^= (*x << 4);
}

Mi překladač hlásí: Upozornění #63-D shift count is too large

Volání funkce:

hostRandomGen(&rngSeed);

¨
Definice:

unsigned long rngSeed = timems();

V čem je problém ?

 
Nahoru Odpovědět
26. října 0:16
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:26. října 10:00

Shiftuješ s příliš vysokou hodnotou.

Pro generování náhodného čísla můžeš použít xorshift32.

uint32_t xorshift32(uint32_t* x) {
        *x ^= *x << 13;
        *x ^= *x >> 17;
        *x ^= *x << 5;
        return *x;
}

kde x je ukazatel na seed, kterému jeho počáteční hodnotu můžeš nastavit např. takto:

time_t t;
uint32_t seed;

time(&t);
seed = (uint32_t)(t);
Nahoru Odpovědět
26. října 10:00
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:26. října 23:04

Díky, nechal jsem původní kód. Zjistil jsem, že je v Linuxu unsigned long 8 bytů, ve Win64 jen 4 byty. Přejmenoval jsem proto definice unsigned long na uint64_t

Mám také problém s úpravou funkce timems(), kterou jsme zde již řešili v příspěvku "Diskuze: Jak upravit program pro hledání hesla ?"

Udělal jsem si krátký testovací program a něco je tam špatně.

#include <iostream>

//Replacement of the Linux gettimeofday(&end, NULL); function and #include <sys/time.h>
#include <stdio.h>
#include <winsock2.h> // struct timeval
#include <windows.h> // timeGetTime()

typedef unsigned long DWORD;

int gettimeofday(struct timeval* tp, void* tzp);
long long timems(void);

int gettimeofday(struct timeval* tp, void* tzp) {
    DWORD t;

    t = timeGetTime();
    tp->tv_sec = t / 1000;
    tp->tv_usec = t % 1000;

    return 0;
}

long long timems(void) {
    struct timeval end;
    gettimeofday(&end, NULL);
    return end.tv_sec * 1000LL + end.tv_usec / 1000;
}


int main()
{
    while (1) {
        long long rngSeed = timems();
        printf("%lld\n", rngSeed);
        Sleep(2);
    }
}

Hlásí mi to chybu:
LNK2019 Nerozpoznaný externí symbol __imp_timeGetTime odkazovaný ve funkci "int __cdecl gettimeofday(struct timeval *,void *)" ([email protected]@[email protected]@[email protected]) timems

 
Nahoru Odpovědět
26. října 23:04
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
DarkCoder:26. října 23:39

To je chyba linkeru, dost pravděpodobně si v projektu nezastavil vše potřebné, jako cesty a soubory. V již zmiňované diskuzi máš celý program, který jsem ti poslal. Ve tvém nejnovějším programu Ti chybí následující řádek který já v programu mám.

#pragma comment( lib, "winmm.lib")
Akceptované řešení
+20 Zkušeností
+2,50 Kč
Řešení problému
Nahoru Odpovědět
26. října 23:39
"Chceš-li předávat své znalosti, měj kvalitní podklady."
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
Caster:27. října 0:16

Díky, pomohlo to. Nyní bez chyby.

 
Nahoru Odpovědět
27. října 0:16
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 17 zpráv z 17.