验证内存是否已在C中初始化

Pau*_*den 5 c memory-management

我编写了一个API,需要初始化上下文,然后传递给每个API调用.调用者为上下文分配内存,然后使用其他参数将其传递给init函数,这些参数描述了他们希望以后的API调用的行为方式.上下文是不透明的,所以客户端不能真正在那里捣乱; 它仅用于API函数的内部使用.

我遇到的问题是调用者正在分配上下文,但没有初始化它.因此,后续API函数指的是无意义的垃圾,就好像它是真实的上下文一样.

我正在寻找一种方法来验证传递给API函数的上下文是否已经初始化.我不确定这是否可行.我想到的两个想法是:

  1. 使用预定义的常量并将其存储在上下文的"魔术"字段中,以便在API调用时进行验证.
  2. 使用上下文内容的校验和,将其存储在"magic"字段中并在调用时验证它.

不幸的是,我知道这些选项中的任何一个都可能导致误报验证,因为内存中的随机垃圾与"魔术"数字相匹配,或者因为上下文恰好占用了与先前初始化的上下文相同的空间.我认为后一种情况更有可能发生.

这简单归结为概率问题吗?在大多数情况下,我可以避免误报,但不是全部?是否值得使用一个只给我一个合理的准确概率的系统,或者这只会让调试其他问题变得更加困难?

Law*_*Dol 6

我认为,最佳解决方案是将create()/ delete()函数添加到API中,并使用create来分配和初始化结构.您可以在结构的开头放置一个签名,以验证您传递的指针指向使用create()分配的内存,并在释放内存之前使用delete()覆盖签名(或整个缓冲区).

你实际上无法避免在C中出现误报,因为调用者malloc的内存"发生"从你的签名开始; 但让你的签名合理地长(比如8个字节)并且赔率很低.但是,通过提供create()函数从调用者手中分配将会有很长的路要走.

而且,是的,你最大的风险是在没有使用delete()的情况下释放初始化的缓冲区,并且后续的malloc碰巧重用了那个内存块.


180*_*ION 3

您的上下文变量目前可能是某种指向已分配内存的指针。相反,将其设为可以显式验证的令牌或句柄。每次初始化上下文时,您都会返回一个新令牌(不是实际的上下文对象)并将该令牌存储在内部列表中。然后,当客户稍后向您提供上下文时,您可以通过查看列表来检查它是否有效。如果是,则可以将令牌转换为实际上下文并使用,否则返回错误。

typedef Context long;

typedef std::map<Context, InternalContext> Contexts;
Contexts _contexts;

Context nextContext()
{
  static Context next=0;
  return next++;
}

Context initialise()
{
  Context c=nextContext();
  _contexts.insert(make_pair(c, new InternalContext));
  return c;
}

void doSomethingWithContext(Context c)
{
  Contexts::iterator it=_ _contexts.find(c);
  if (it==_contexts.end())
    throw "invalid context";
  // otherwise do stuff with the valid context variable
  InternalContext *internalContext=*it.second;
}
Run Code Online (Sandbox Code Playgroud)

使用此方法,不存在无效内存访问的风险,因为您只会正确使用有效的上下文引用。