Как может я grep для текстового шаблона в заархивированном текстовом файле?

Исходный ответ
{
    void *mem = malloc(1024+16);
    void *ptr = ((char *)mem+16) & ~ 0x0F;
    memset_16aligned(ptr, 0, 1024);
    free(mem);
}

Фиксированный ответ

{
    void *mem = malloc(1024+15);
    void *ptr = ((uintptr_t)mem+15) & ~ (uintptr_t)0x0F;
    memset_16aligned(ptr, 0, 1024);
    free(mem);
}

Объяснение, как требуется

первый шаг должен выделить достаточно запасного места на всякий случай. Так как память должна составить выровненных 16 байтов (подразумевать, что ведущий адрес байта должен быть кратным 16), добавляя, что 16 дополнительных байтов гарантируют, что у нас есть достаточно пространства. Где-нибудь в первых 16 байтах, существует выровненный указатель 16 байтов. (Обратите внимание, что malloc(), как предполагается, возвращает указатель, который является достаточно хорошо выровненный для [1 159] любой цель. Однако значение 'любого', прежде всего, для вещей как основные типы — long, double, long double, long long, и указатели на объекты и указатели на функции. Когда Вы делаете более специализированные вещи, как игра с графическими системами, им может быть нужно более строгое выравнивание, чем остальная часть системы — следовательно вопросы и ответы как это.)

следующий шаг должен преобразовать пустой указатель на символьный указатель; GCC, несмотря на это, Вы, как предполагается, не делаете адресную арифметику с указателями на пустых указателях (и GCC имеет предупреждение опций сказать Вам при злоупотреблении его). Тогда добавьте 16 к указателю запуска. Предположим malloc(), возвратил Вас невозможно плохо выровненный указатель: 0x800001. Добавление этих 16 дает 0x800011. Теперь я хочу округлить в меньшую сторону до 16-байтовой границы —, таким образом, я хочу сбросить последние 4 бита к 0. 0x0F имеет последний набор на 4 бита одному; поэтому, ~0x0F имеет весь набор битов одному кроме последних четырех. Выполнение операции "И", которое с 0x800011 дает 0x800010. Можно выполнить итерации по другим смещениям и видеть, что та же арифметика работает.

последний шаг, free(), легок: Вы всегда, и только, возвращаетесь к [1 114] значение, что один из [1 115], calloc() или realloc() возвратил Вам —, что-либо еще - бедствие. Вы правильно обеспечили mem для содержания того значения — спасибо. Бесплатные выпуски это.

Наконец, если Вы знаете о внутренностях своей системы malloc пакет, Вы могли бы предположить, что это могло бы хорошо возвратиться, 16 байтов выровняли данные (или это могли бы быть выровненных 8 байтов). Если бы это были выровненных 16 байтов, то Вы не должны были бы укорачивать со значениями. Однако это - изворотливый и непортативный — другой malloc, пакеты имеют различное минимальное выравнивание и поэтому принятие одной вещи, когда это делает что-то другое привело бы к дампам ядра. В широких пределах это решение является портативным.

Кто-то еще упомянул posix_memalign() как другой способ получить выровненную память; это не доступно везде, но могло часто реализовываться с помощью этого в качестве основания. Обратите внимание, что было удобно, что выравнивание было питанием 2; другое выравнивание более грязно.

Еще один комментарий — этот код не проверяет что выделение, за которым следуют.

Windows Programmer Поправки

указал, что Вы не можете сделать операций битовой маски на указателях, и, действительно, GCC (3.4.6 и 4.3.1 протестированных) действительно жалуется как этот. Так, исправленная версия абсолютного кода — преобразованный в основную программу, следует. Я также брал на себя смелость добавления всего 15 вместо 16, как был указан. Я использую uintptr_t, так как C99 был вокруг достаточно долго, чтобы быть доступным на большинстве платформ. Если бы это не было для использования [1 123] в эти printf() операторы, это было бы достаточно к [1 125] вместо того, чтобы использовать #include . [Этот код включает фиксацию, на которую указывают [1 151] C.R. , который повторял мнение, сначала высказанное [1 152] счет K много лет назад, который мне удалось пропустить до сих пор.]

#include 
#include 
#include 
#include 
#include 

static void memset_16aligned(void *space, char byte, size_t nbytes)
{
    assert((nbytes & 0x0F) == 0);
    assert(((uintptr_t)space & 0x0F) == 0);
    memset(space, byte, nbytes);  // Not a custom implementation of memset()
}

int main(void)
{
    void *mem = malloc(1024+15);
    void *ptr = (void *)(((uintptr_t)mem+15) & ~ (uintptr_t)0x0F);
    printf("0x%08" PRIXPTR ", 0x%08" PRIXPTR "\n", (uintptr_t)mem, (uintptr_t)ptr);
    memset_16aligned(ptr, 0, 1024);
    free(mem);
    return(0);
}

И вот незначительно более обобщенная версия, которая будет работать на размеры, которые являются питанием 2:

#include 
#include 
#include 
#include 
#include 

static void memset_16aligned(void *space, char byte, size_t nbytes)
{
    assert((nbytes & 0x0F) == 0);
    assert(((uintptr_t)space & 0x0F) == 0);
    memset(space, byte, nbytes);  // Not a custom implementation of memset()
}

static void test_mask(size_t align)
{
    uintptr_t mask = ~(uintptr_t)(align - 1);
    void *mem = malloc(1024+align-1);
    void *ptr = (void *)(((uintptr_t)mem+align-1) & mask);
    assert((align & (align - 1)) == 0);
    printf("0x%08" PRIXPTR ", 0x%08" PRIXPTR "\n", (uintptr_t)mem, (uintptr_t)ptr);
    memset_16aligned(ptr, 0, 1024);
    free(mem);
}

int main(void)
{
    test_mask(16);
    test_mask(32);
    test_mask(64);
    test_mask(128);
    return(0);
}

Для преобразования test_mask() в функцию выделения общего назначения единственное возвращаемое значение от средства выделения должно было бы закодировать адрес выпуска, как несколько человек указали в их ответах.

проблемы с интервьюерами

прокомментированный Uri: Возможно, у меня есть проблема понимания прочитанного этим утром, но если вопрос об интервью конкретно говорит: "Как Вы выделили бы 1 024 байта памяти", и Вы ясно выделяете больше, чем это. Это не было бы автоматическим отказом от интервьюера?

Мой ответ не впишется в комментарий с 300 символами...

Это зависит, я предполагаю. Я думаю, что большинство людей (включая меня) ответило на вопрос для значения, "Как Вы выделите место, в котором 1 024 байта данных могут быть сохранены, и где базовый адрес является кратным 16 байтам". Если интервьюер действительно имел в виду, как можно выделить 1 024 байта (только) и иметь его выровненных 16 байтов, то опции более ограничены.

  • Очевидно, одна возможность состоит в том, чтобы выделить 1 024 байта и затем предоставить тому адресу 'лечение выравнивания'; проблема с тем подходом состоит в том, что фактическое свободное место не является правильно определенным (применимое пространство между 1008 и 1 024 байтами, но не было механизма, доступного для определения, какой размер), который представляет его менее, чем полезный.
  • Другая возможность состоит в том, что Вы, как ожидают, запишете полное средство выделения памяти и удостоверитесь, что 1 024-байтовый блок, который Вы возвращаете, соответственно выровненный. Если это так, Вы, вероятно, заканчиваете тем, что делали операцию, довольно подобную тому, что сделало предлагаемое решение, но Вы скрываете его в средстве выделения.

Однако, если бы интервьюер ожидал любой из тех ответов, я ожидал бы, что они распознают, что это решение отвечает на тесно связанный вопрос, и затем повторно структурировать их вопрос указать на разговор в корректном направлении. (Далее, если бы интервьюер добрался действительно stroppy, то я не хотел бы задания; если ответ на недостаточно точное требование подстрелен в провокационных сообщениях без исправления, то интервьюер не кто-то, на кого безопасно работать.)

мировые перемещения на [1 168]

заголовок вопроса недавно изменился. Это было , Решают выравнивание памяти в вопросе об интервью C, который озадачил меня . Пересмотренный заголовок (, Как выделить выровненную память, только пользующуюся стандартной библиотекой? ), требует, чтобы немного пересмотренный ответ — это приложение обеспечил его.

C11 (ISO/IEC 9899:2011) добавленная функция aligned_alloc():

7.22.3.1 aligned_alloc функция

Описание
Резюме

#include 
void *aligned_alloc(size_t alignment, size_t size);

Эти aligned_alloc функция выделяет место для объекта, выравнивание которого определяется [1 131], чей размер определяется [1 132], и чье значение неопределенно. Значение [1 133] должно быть допустимым выравниванием, поддерживаемым реализацией, и значение [1 134] должно быть интегралом несколько из [1 135].

Возвраты
aligned_alloc функция возвращает или нулевого указателя или указатель на выделенное место.

И POSIX определяет posix_memalign() :

#include 

int posix_memalign(void **memptr, size_t alignment, size_t size);

ОПИСАНИЕ

Эти posix_memalign() функция должна выделить size байты, выровненные на границе, определенной [1 140], и должна возвратить указатель на выделенную память в [1 141]. Значение [1 142] должно быть питанием два несколько из [1 143].

После успешного завершения, значение, на которое указывают [1 144], должно быть кратным [1 145].

, Если размер пространства, которое требуют, 0, поведение определяется реализацией; значение, возвращенное в [1 146], должно быть или нулевым указателем или уникальным указателем.

Эти free() функция должна освободить память, которая была ранее выделена [1 148].

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

После успешного завершения, posix_memalign() должно возвратить нуль; иначе код ошибки должен быть возвращен для указания на ошибку.

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

Негласно, новая выровненная функция памяти делает почти такое же задание, как обрисовано в общих чертах в вопросе, кроме у них есть способность вызвать выравнивание более легко и отслеживать запуск выровненной памяти внутренне так, чтобы код не имел дело с особенно —, это просто освобождает память, возвращенную функцией выделения, которая использовалась.

20
задан dawntrader 8 August 2009 в 20:24
поделиться

3 ответа

zgrep в Linux. Если вы работаете в Windows, вы можете загрузить GnuWin , который содержит порт zgrep для Windows.

25
ответ дан 30 November 2019 в 00:31
поделиться

Командлеты PowerShell Community Extensions (PSCX) включают Read-Archive и Expand-Archive , но не включают (пока?) Поставщика навигации, который сделает то, что вы хотите, очень простым. Тем не менее, вы можете использовать Чтение-архив и Расширение-архив . Что-то вроде этого непроверенного бита

Read-Archive -Path foo.zip -Format Zip | `
   Where-Object { $_.Name -like "*.txt" } | `
      Expand-Archive -PassThru | select-string "myRegex"

позволит вам выполнять поиск без извлечения всего архива.

4
ответ дан 30 November 2019 в 00:31
поделиться

В расширения сообщества Powershell (PSCX) . Однако я не думаю, что они будут делать то, что вы хотите (хотя я могу ошибаться в этом). Вместо этого я бы использовал .Net Zip Library (DotNetZip) , которая позволяет вам по существу перечислить имена файлов в архиве, а затем извлечь только те, которые вам нужны.

2
ответ дан 30 November 2019 в 00:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: