【问题标题】:What is the meaning of operation in cc中的操作是什么意思
【发布时间】:2020-01-03 05:24:09
【问题描述】:

我正在尝试序列化 PHP 操作码。我对代码感到困惑。请检查以下代码。代码是什么意思。

(ptr) = (void*)((char*)(ptr) - (char*)script->mem)

https://github.com/php/php-src/blob/6aaab9adf7619c121c19701022aeb8d88f9c3bab/ext/opcache/zend_file_cache.c#L112

如何序列化op_array

【问题讨论】:

标签: c gcc


【解决方案1】:

所以,这是一个古老的游戏编码器技巧,旨在序列化/反序列化指向/来自磁盘的指针。

这有点脏,但让我看看能不能解释一下。使用一个非常简单的例子,让我们想象一下我有这个结构:

struct FileContents
{
  char text[10] = {0,1,2,3,4,5,6,7,8,9};
  char* ptr = text + 5; //< point to element 5
};

我想一次性使用 fread/fwrite 读/写该结构。如果我只是这样做:

void writeFile(FileContents contents)
{
  FILE* fp = fopen("blah.dat", "wb");
  fwrite(&contents, sizeof(FileContents), 1, fp);
  fclose(fp);
}

这对于存储在 contents.text 中的值可以正常工作,但对于 contents.ptr 会非常失败(因为这个指针指向一个内存地址,我们不太可能重新声明它如果我们想再次读取数据,则使用相同的内存位置)

因此,我们需要对所有指针值进行 unfix/refix 操作。我们可以这样做:

struct FileContents
{
  char text[10] = {0,1,2,3,4,5,6,7,8,9};
  void* ptr = (text + 5); //< point to element 5

  // convert 'ptr' to be an integer offset from the start of the struct
  void unfix()
  {
    // heres the first byte we will write to the file
    char* startOfFile = (char*)this;

    // here's the problematic pointer value.
    char* ptrValue = ptr;

    // now lets compute a byte offset from the start of the struct,
    // to the memory location ptr is pointing to... 
    // (in this case, the offset will be 5)
    size_t offset = ptrValue - startOfFile;

    // now lets modify the value of ptr so that it now stores a byte 
    // offset, rather than a memory location. (We need to cast the 
    // offset to a pointer value, otherwise this wont work)
    ptr = (void*)offset;
  }

  // AFTER reading the file (deserialise), we need to convert
  // that integer offset back into a valid memory address...
  void refix()
  {
    // grab start of struct in memory
    char* startOfFile = (char*)this;

    // and add the offset to the start of the file, to
    // get the valid memory location
    ptr = startOfFile + ((size_t)ptr);
  }  
};

【讨论】:

  • 在回答 C 问题时要小心使用 C++ 符号。您在结构中的初始化程序以及在结构定义范围内包含的函数定义都是 C++ 而不是 C。
  • 谢谢... 将复杂结构(op_array)写入磁盘的新方法是什么?
  • 这仅适用于指向结构中内存地址的指针,对吧?
  • @LegendofPedro 没错。它基本上是一种将整个资产从磁盘加载到单个内存块中的方法,并且仍然能够使用该数据中的指针来提供快速访问(而不必计算那些偏移量和地址)。
  • 这种技术只对加载时不变的文件数据有帮助,不需要经常重新评估,并且有快速加载和查找时间会很好。您链接到的代码看起来好像为调试器(或解释器)形成了某种形式的程序数据库?这有点道理。链接时生成一次 pdb,然后您可以非常快速地加载/查询数据结构以供调试器(或解释器)使用
【解决方案2】:

您似乎有void* ptrsometype* script-&gt;mem,将它们都转换为char* 并从另一个中减去,然后将结果转换为void*

【讨论】:

    猜你喜欢
    • 2011-02-09
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2018-07-31
    • 2015-06-09
    • 1970-01-01
    相关资源
    最近更新 更多