0

我在 C 中插入 memcpy() 函数,因为目标应用程序使用它来连接字符串,我想找出正在创建的字符串。代码是:

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

4 回答 4

2

由于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*......)。

无论如何,对于某些可能没问题的情况。

于 2010-09-30T17:47:09.610 回答
1

您可以先对复制的内存应用一些启发式方法,然后根据此决定是否要打印它。

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';

如果你也想抓住它,你将不得不改变上面的函数。

于 2010-09-30T17:47:47.097 回答
0

ret等于目标指针。但是无法确定它是数组还是字符串,除非您知道有关数组或字符串的更多信息(例如,字符串具有一定长度并且以空值结尾)。

于 2010-09-30T17:45:01.987 回答
0

不,您无法从 void 类型的指针中弄清楚这一点。另外,您不知道源或目标的大小,因此启发式方法不起作用。由于其他原因,它也不起作用,例如存储在指向的内存区域中的二进制数据void*实际上可以在末尾有零字节,但这并不意味着它是字符串。

于 2010-09-30T17:55:55.207 回答