Ответы пользователя по тегу C++
  • Как реализован внутри std::tm?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В чем тут фокус?

    Нет никакого фокуса. std::tm -- это завёрнутая в namespace std struct tm, древняя структура из чистого C.
    Ответ написан
  • Как быстро округлить timestamp до секунд, минут, часов, дней и т.д.?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Я думаю, что пара gmtime + timegm -- это простое, понятное, сравнительно портабельное и довольно быстрое решение:
    #include <time.h>
    
    enum time_floor_level {
        YEAR, MONTH, DAY, HOUR, MINUTE,
    };
    
    time_t time_floor(time_t t, enum time_floor_level level)
    {
        struct tm tm;
    
        gmtime_r(&t, &tm);
    
        switch (level) {
        case YEAR:
            tm.tm_mon = 0;
        case MONTH:
            tm.tm_mday = 1;
        case DAY:
            tm.tm_hour = 0;
        case HOUR:
            tm.tm_min = 0;
        case MINUTE:
            tm.tm_sec = 0;
        }
        return timegm(&tm);
    }
    Ответ написан
    Комментировать
  • Что означает ошибка "Error: relocation ... cannot be used with -shared"?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что означает ошибка «Error: relocation ... cannot be used with -shared»

    Эта ошибка значает, что такой объектник содержит код, работа которого зависит от адреса по которому он будет размещён. Так называемый position-dependent code. Альтернатива -- position-independent code, такой, который выполняется одинаково, независимо от адреса, а все данные и константы, которые зависят от адреса, если таковые есть, вынесены из кода в отдельный изменяемый сегмент. Такой код генерируется компилятором если его вызывать с правильным флагом (например gcc -fpic). Из-за того что динамические библиотеки могут быть загружены в процесс по любому адресу существует требование, что код в них должен быть position-independent. Поэтому объектники скомпилированные как position-dependent обычно не могут быть слинкованы в динамическую библиотеку.

    В данном случае запись о релокации с типом R_AARCH64_TLSLE_ADD_TPREL_HI12 говорит (частью TLSLE, где LE означает Local Executable) о том, что код объектника в котором она находится был намеренно собран с рассчётом на то, что объектник будет частью исполняемого файла, а не динамической библиотеки. Здесь можно почитать об отличиях моделей адресации TLS, в частности о модели Local Exec в разделе 4.4.
    Ответ написан
    Комментировать
  • Почему возникает проблемы при закрытие файла в C++ с использованием std.io?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему возникает проблемы при закрытие файла

    Почему ты решил, что при закрытии? Сообщение явно приходит из реализации fwrite.

    Ошибка вызвана тем, что в функцию fwrite передаётся NULL в качестве указателя на FILE. Для предотвращения этой ошибки нужно проверять, что файл был успешно открыт перед тем как читать из него или писать в него.
    Ответ написан
  • Почему цикл в C++ застревает?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Больших отличий я не заметил


    Я удалил неважные части кода, чтобы большое отличие стало более заметно. Вот что получилось из твоего кода:
    while (num_bor_1 <= num_bor_2)
      {
        if ((num_bor_1 % 2) != 1)
        {
          num_bor_1++;
        }
      }


    А вот что получилось из решения:
    do
      {
        num_bor_1++;
      } while (num_bor_1 < num_bor_2);
    Ответ написан
    Комментировать
  • Почему возникает free(): double free detected in tcache 2? (в деструкторе)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему возникает free(): double free detected

    Потому что в этом классе не реализован конструктор копирования (а так же перемещения и операторы присваивания, но это пока не вызывает таких же ошибок). В результате при копировании объекта класса String копия получает то же значение str что и оригинал с которого она скопирована, в деструкторе копия удаляет str оригинала, а потом это же делает оригинал в своём деструкторе. См. правило трёх/пяти.
    Ответ написан
    Комментировать
  • Можно ли как то скачать URL сайта сразу в переменную?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Можно заменить URLDownloadToFileA на URLOpenBlockingStream и читать данные из интерфейса IStream который возвращает эта функция.
    Ответ написан
    3 комментария
  • Как правильно считать значение из бинарного файла C++?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    third = string(buffer1);
    fourth = string(buffer2);

    Должно быть
    third = string(buffer1, size3);
    fourth = string(buffer2, size4);

    поскольку строки прочитанные в buffer1 и buffer2 не 0-терминированные.

    И отдельно
    char buffer1[size3];

    char buffer2[size4];

    это не по стандарту С++, компилируется и работает только из-за расширений GNU.
    Ответ написан
    5 комментариев
  • Почему выводятся не те символы, которые прописаны в коде?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    wcout << endl << "Результат: " << encrypt(s);

    ты потерял L перед "Результат" и выводишь в wcout обычную строку.

    А перед этим выводишь в cout. Приведи всё к выводу в wcout.

    Стандарт C++ об этом говорит вот что:
    Mixing operations on corresponding wide- and narrow-character streams follows the same semantics as mixing such operations on FILEs, as specified in the C standard library.

    А стандарт С в свою очередь говорит вот что (C11 7.21.2:4):

    Each stream has an orientation. After a stream is associated with an external file, but
    before any operations are performed on it, the stream is without orientation. Once a wide
    character input/output function has been applied to a stream without orientation, the
    stream becomes a wide-oriented stream. Similarly, once a byte input/output function has
    been applied to a stream without orientation, the stream becomes a byte-oriented stream.
    Only a call to the freopen function or the fwide function can otherwise alter the
    orientation of a stream. (A successful call to freopen removes any orientation.)

    Byte input/output functions shall not be applied to a wide-oriented stream and wide
    character input/output functions shall not be applied to a byte-oriented stream.
    Ответ написан
    7 комментариев
  • Программа не отвечает на кириллические символы - что делать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Помогите мне, пожалуйста, решить эти проблемы

    При условии правильной настройки переменных окружения достаточно заменить setlocale(LC_ALL, "ru"); на setlocale(LC_ALL, "");.
    Ответ написан
  • Как расширить размер динамического массива типа string в с++?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как расширить размер с сохранением данных(realloc) с массивом string в с++

    Думаю, что по честному (т.е. не завязываясь на конкретное внутреннее представление string) -- никак, только выделив новый массив и скопировав/переместив объекты из старого массива в новый. Имеет смысл эту работу делегировать стандартному контейнеру vector, где эта логика уже должна быть реализована.
    Ответ написан
    Комментировать
  • Может ли прерывание прервать выполнение конструктора / деструктора в С++?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Может ли прерывание прервать выполнение конструктора / деструктора в С++?

    Да, конечно может, как и любой другой код, явно не защищённый от прерываний.

    нужно ли в конструкторах / деструкторах защищать код критическими секциями?

    Нужно защищать любое состояние, к которому может обращаться код из разных контекстов выполнения -- например из разных потоков или из потока и обработчика прерывания. В ядре linux (где разных типов контекста много и разных способов синхронизации тоже много) есть руководство, что и когда использовать.
    Ответ написан
    Комментировать
  • Очень странная ошибка MPI?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    в чем ее суть

    в том, что процесс с rank == 0 посылает сообщение самому себе, и это становится для него неожиданностью.

    как с ней бороться

    как вариаент -- не посылать сообщение самому себе из процесса с rank == 0. Например так:
    if(rank == 0){
            for(size_t i = 1; i < size; i++){

    надо будет, конечно, пересмотреть все места где работа разделяется на size частей, и скорректировать для size - 1.
    Ответ написан
    Комментировать
  • Почему компилятор не генерирует конструктор по умолчанию в отдельной единице трансляции?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему компилятор не генерирует конструктор

    потому что нигде не написано, что он должен? Я вижу, что в коде генерируемом gcc инициализация таблицы виртуальных функций инлайнится по месту создания объекта, вне зависимости от опций оптимизации.
    Ответ написан
    1 комментарий
  • Почему можно не указывать virtual в файле реализации?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему можно не указывать virtual в файле реализации?

    Не то чтобы "можно не указывать". Нужно не указывать. Потому что так говорит стандарт.
    И потому что виртуальность функции -- это не свойство функции, а свойство класса которому она принадлежит. Код функции не зависит от того, виртуальная она или нет.
    Ответ написан
    4 комментария
  • Почему виснит программа на MPI?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему виснет программа на MPI?

    Потому что процесс с rank = 0 хочет послать VEC_SIZE сообщений, а процессы с rank > 0 обрабатывают каждый только по одному сообщению, после чего завершаются. Тебе нужно как-то объяснить исполнителям, сколько запросов они должны обработать перед завершением. Например так:

    if(rank == 0){
                    for(int i = 0; i < VEC_SIZE; i++){
                            …
                    }
                    for (int i = 1; i < size; ++i) {
                            int q = -1;
                            MPI_Send(&q, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
                    }
            }else{
                    for (;;) {
                            int index;
                            MPI_Status status;
                            MPI_Recv(&index, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
                            if (index < 0)
                                    break;
                            …
                    }
            };


    Отдельно стоит сказать о том, что цикл который посылает задачу процессу и тут же ждёт результата от этого же самого процесса не имеет смысла с точки зрения улучшения производительности. Имеет смысл сначала разослать задания свободным исполнителям, а только после этого начинать ждать от них ответов.

    И ещё по мелочи:
    for(size_t i = 0; i < VEC_SIZE; i++){
                size_t num_process = (i % (size - 1)) + 1;
                MPI_Send(&i, 1, MPI_INT, static_cast<int>(num_process), 0, MPI_COMM_WORLD);

    размер size_t i может отличаться от размера int, подразумеваемого типом MPI_INT. Этот код точно будет работать неправильно на big-endian архитектурах с LP64 ABI.
    Ответ написан
    Комментировать
  • Не работает деструктор. В чем ошибка?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Не работает деструктор

    "Не работает деструктор" -- это когда программу компилируешь, запускаешь, а деструктор не делает того, что в нём написано. У тебя же программа не компилируется. Из-за того, что в настройках компилятора стоит "трактовать предупреждения как ошибки" и "предупреждать о неэффективном коде С++". Ну и вдобавок, предупреждение тебе правильно говорит, что если ты не реализовал конструктор копирования и оператор присваивания для класса самостоятельно управляющего памятью, то жди проблем, когда начнёшь копировать объекты этого класса.
    Ответ написан
    6 комментариев
  • Как сделать сжатие и распаковку char* в C++ с помощью zlib?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    что я делаю не так?

    Несколько вещей. В compress_char ты сначала выделяешь strlen(source) байт для вывода, а потом находишь compSize, который может быть и больше чем strlen(source). Ты не возвращаешь compSize после вызова compress, а он может измениться. Ты возвращаешь только char*, как будто это строка, но это не строка, там могут быть нулевые байты.
    В uncompress_char почти те же самые ошибки. Плюс какая-то путаница между length, compSize и ucompSize. На вход uncompress в параметре compSize должен попасть настоящий размер сжатых данных, а не догадка о нём на основе вызова compressBound.
    Я бы поменял код как-то так:
    char* compress_char(const char* source, size_t *outCompSize, size_t *outUcompSize)
    {
        uLong ucompSize = strlen(source) + 1;
        uLong compSize = compressBound(ucompSize);
        char* bytes = malloc(compSize);
        compress((Bytef *)bytes, &compSize, (Bytef *)source, ucompSize);
        *outCompSize = compSize;
        *outUcompSize = ucompSize;
        return bytes;
    }
    
    char* uncompress_char(const unsigned char source[], size_t inCompSize, size_t inUcompSize)
    {
        uLong ucompSize = inUcompSize;
        uLong compSize = inCompSize;
        char* message = malloc(ucompSize);
        uncompress((Bytef *)message, &ucompSize, (Bytef *)source, compSize);
        return message;
    }
    
    void foo(void)
    {
        size_t a, b;
        char *p = compress_char("{\"a2\":\"b\"}", &a, &b);
        char *p1 = uncompress_char(p, a, b);
        printf("%s, %zd -> %zd\n", p1, b, a);
    }


    Плюс ты не обрабатываешь коды возврата из compress/uncompress.
    Ответ написан
    Комментировать
  • Статическое подключение zlib в .so?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    У меня есть код на C++, который использует zlib. Я хочу на линуксе его скомпилировать в .so библиотеку, но чтобы команда ldd не показывала libz.so или libz.so.1 (чтобы zlib был встроен в .so).

    Ключами линковщика -Bstatic и -Bdynamic можно переключать режим линковки библиотек:
    g++ -shared foo.cc -o libfoo.so -Wl,-Bstatic -lz -Wl,-Bdynamic

    Но если так сделать, то можно заметить, что не всякую статическую библиотеку можно прилинковать к .so, а только такую, объектники которой собраны с флагом -fpic.
    Ответ написан
  • Почему substr работает странно?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Последняя кавычка ни в какую не хочет убираться, не могу понять, в чем дело
    std::string variable_value = var.substr(variable_value_start + 1, variable_value_end - 1);

    Второй параметр std::string::substr -- это длина выделяемой подстроки, а не индекс конца.
    Должно быть
    std::string variable_value = var.substr(variable_value_start + 1,
                                            variable_value_end - variable_value_start - 1);
    Ответ написан