[C++] realloc() i memcpy() - Co jest z nimi nie tak?

0

Witam.
Piszę malutki programik, który z tego co ja mu powpisuje sklei mi pewne wyrażenie regularne...
No i mam pewien problem z funkcjami wymienionymi w temacie... Jak tak czytać ten kod to wygląda że wszystko jest dobrze. A jak skompiluje go to strlen() zwraca mi długość tego wyrażenia o 1 większą niż jak sobie krokami liczę rozmiar tego wyrażenia (ciągu znakowego).

Oto cały kod (jest to tylko kawałeczek programu bo mi w tym momencie przystawiło :/). Bardzo prosze kogoś o przekompilowanie go na swojej maszynie i ew. wytłumaczenie dlaczego jest tak a nie inaczej :/

W main wystarczy tą funkcję wywołać i się wyśiwetli... u mnie oprócz tego "ciulowego wyrażenia" zwraca mi 46 i 47...

    char * * BuildQueryArray_USER()
    {
        char * query_table[4] =
        {
            "SELECT (",
            "SELECT COUNT ",
            "INSERT INTO ",
            "UPDATE ",
        };
        char * querys_end = "='.*';";
      // Interpunklc
        char * log_or = "|";
        char * log_next = "(,[ ]{0,1}){0,1}";
        char * section_end = ") ";

      // bufor dla skłądania zapytań
        char * buffer = NULL;
        int buffer_len = 0;
        int buffer_len2 = 0;

      // SELECT
        int select_len = 0;
        char * select_columns[] =
        {
            "`id`",
            "`links`",
            "`domain`",
        };

        buffer = (char*) realloc((void*)buffer, buffer_len+1);
        memcpy(buffer, "(", 1);
        buffer_len++;
      // Składanie sekcji wybierania wyświetlanych kolumn
        for(int i = 0; i < (sizeof(select_columns)/sizeof(char *)); i++)
        {
            for(int j = 0; j < 2; j++)
            {
              // Dodanie kolumny
                buffer = (char*) realloc((void*)buffer, buffer_len+strlen(select_columns[i]));
                memcpy(buffer+buffer_len, select_columns[i], strlen(select_columns[i]));
                buffer_len += strlen(select_columns[i]);

              // Dodanie OR
                buffer = (char*) realloc((void*)buffer, buffer_len+1);
                memcpy(buffer+buffer_len, "|", 1);
                buffer_len += 1;
            }
        }
        buffer = (char*) realloc((void*)buffer, buffer_len+1);
        memcpy(buffer+buffer_len, ")", 1);
        buffer_len++;
      // Wyświetlenie buforu
        cout << buffer << endl << buffer_len << endl << strlen(buffer) << endl;
        return query_table;
    }

A teraz ciekawostka!! Jak zamiast

        char * select_columns[] =
        {
            "`id`",
            "`links`",
            "`domain`",
        };

dam

        char * select_columns[] =
        {
            "`id`",
            "`links`",
            "`domain",
        };

(czyli tylko o jeden znak zmniejszyłem jeden podciąg znakowy) to zwraca mi 44 i też 47!! ;/
A jak zwiększę ten sam podciąg o jeden znak to zwróci mi 48 i 48 ;/

Czy to coś z moim kompilatorem jest nie tak czy jaka cholera :/

0

mi zwraca 46 i 47
a znak \0 ma się sporo, bo strlen zwraca ci długość bez znaku, a buffer_len chyba będzie zawierał(nie chce mi się dokładniej analizować) długość z \0

btw. jak dla mnie bardzo zła koncepcja, realokowanie to mnóstwo niepotrzebnych przekopiowań, a im ciąg dłuższy tym dłuższe kopiowania
ja to bym zrobił: -obliczam długość bufora, tworzę go, wypełniam

0
coder() napisał(a)

Czy to coś z moim kompilatorem jest nie tak czy jaka cholera

Odczep się od kompilatora i weź przeanalizuj jeszcze raz kod pod kątem wstawiania znaku NULL na końcu kopiowanych stringów.

Jeżeli poprawisz te dwie linijki (prawie na końcu pliku):

        buffer = (char*) realloc((void*)buffer, buffer_len+1);
        memcpy(buffer+buffer_len, ")", 1);

tak, żeby wyglądały w ten sposób:

        buffer = (char*) realloc((void*)buffer, buffer_len+2);
        memcpy(buffer+buffer_len, ")", 2);

to będzie działać dobrze.

I skoro piszesz w C++ i korzystasz z stl'a (cout), to użyj klasy std::string.

Dodatkowo zwracasz wskaźnik do zmiennej lokalnej.

0

No ok... tutaj się z Tobą zgodzę że przeoczyłem ten znak null jak kopiowałem te 2 linijki no ale dlaczego nie mogę do realloca przekazać przy pierwszym wywołaniu tej funkcji bufora który już coś zawiera w sobie... Tylko musze wysyłać do niego pusty bufor (NULL)??

0

O tym mówisz?

char * buffer = " ";
int buffer_len = 1;

buffer = (char*) realloc(buffer, buffer_len+1);

jeśli tak, to w ten sposób nie możesz tego zrobić, bo realloc dostaje wskaźnik na pamięć, która nie jest pamięcią sterty i przy próbie usunięcia tudzież odczytu jej długości będzie błąd.

0
0x666 napisał(a)

jeśli tak, to w ten sposób nie możesz tego zrobić, bo realloc dostaje wskaźnik na pamięć, która nie jest pamięcią sterty i przy próbie usunięcia tudzież odczytu jej długości będzie błąd.
Dokładnie tak. Innymi słowy mówiąc funkcji realloc można podać jedynie wskaźnik na bufor utworzony funkcją malloc lub realloc.

0

adf88 - albo po prostu zero ;) ponizsze jest poprawne i zalecam autorowi

char * buffer = 0;
int buffer_len = 0;
...
buffer_len = /*nowa dlugosc+1*/
buffer = (char*)realloc(buffer, buffer_len);

1 użytkowników online, w tym zalogowanych: 0, gości: 1