Узнайте, является ли полученный указатель строкой, ushort или массивом - PullRequest
0 голосов
/ 30 сентября 2010

Я вставляю функцию memcpy () в C, потому что целевое приложение использует ее для объединения строк, и я хочу выяснить, какие строки создаются. Код:

void * my_memcpy ( void * destination, const void * source, size_t num )
{
    void *ret = memcpy(destination, source, num);
    // printf ("[MEMCPY] = %s \n", ret);
    return ret;
}

Функция вызывается успешно, но первый параметр может быть любым, и я хочу отследить его, только если результатом является строка или массив. Я должен был бы спросить, если это массив или строка. Я знаю, что это не может быть сделано просто: есть ли способ узнать, на что указывает RET?

Я работаю под MACOSX и вставляю в DYLD.

Большое спасибо.

Ответы [ 4 ]

2 голосов
/ 30 сентября 2010

Поскольку void* представляет необработанный блок памяти, невозможно определить, какие именно данные там находятся.

Однако вы можете создать «строковый» дамп памяти для каждой операции, простодать результирующему выводу своего рода «верхний предел вывода».

Это может быть реализовано следующим образом:

const size_t kUpperLimit = 32;

void output_memory_dump(void* memory) {
   std::cout.write(reinterpret_cast<char*>(memory), kUpperLimit);
}

Для нестроковыхкак и данные, вывод будет трудно интерпретируемым, но в противном случае вы получите то, что искали.

Вы можете попытаться применить некоторый основанный на догадках подход, такой как итерация по reinterpret_cast<void*>(memory) и создание is_alphanumeric && is_space проверяет каждый символ, но этот подход не кажется очень стабильным (, кто знает, что на самом деле может лежать в этом void* ... ).

Во всяком случае, дляВ некоторых ситуациях это может быть хорошо.

1 голос
/ 30 сентября 2010

Сначала вы можете применить некоторую эвристику к скопированной памяти и на основании этого вы можете решить, хотите ли вы распечатать ее.

static int maybe_string(const void *data, size_t n) {
  const unsigned char *p;
  size_t i;

  p = data;
  for (i = 0; i < n; i++) {
    int c = p[i];
    if (c == '\n' || c == '\r' || c == '\t')
      continue;
    if (1 <= c && c < 32)
      return 0; /* unusual ASCII control character */
    if (c == '\0' && i > 5)
      return 1; /* null-terminated and more than a few characters long */
  }

  return 0; /* not null-terminated, so it isn't a string */
}

Эта эвристика не идеальна.Например, он не работает для следующего шаблона:

const char *str = "hello, world";
size_t len = strlen(str);
char *buf = malloc(1024);
memcpy(buf, str, len);
buf[len] = '\0';

Если вы хотите это перехватить, вам придется изменить вышеуказанную функцию.

0 голосов
/ 30 сентября 2010

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

0 голосов
/ 30 сентября 2010

ret равно указателю назначения.Но невозможно определить, является ли это массив или строка, если вы не знаете больше информации о массиве или строке (например, строка имеет определенную длину и заканчивается нулем).

...