【问题标题】:Malloc allocates more memory then needed when using soci::use使用 soci::use 时,Malloc 分配的内存比需要的多
【发布时间】:2021-12-31 23:28:42
【问题描述】:

在调查一个奇怪的 tcmalloc 错误时,我和我的同事将错误追溯到一行代码:

soci::session db;
...
db << "INSERT INTO `public.tablename` (..., ..., textvalue) VALUES ('...', '...', :1);",
  soci::use(std::to_string(someStruct.getUint32_t()) + "." + std::to_string(someStruct.getUint32_t()));

一切正常,我们将其更改为:

soci::session db;
...
std::string temp = std::to_string(someStruct.getUint32_t()) + "." + std::to_string(someStruct.getUint32_t());
db << "INSERT INTO `public.tablename` (..., ..., textvalue) VALUES ('...', '...', :1);",
  soci::use(temp);

我们在第一个版本中遇到了 tcmalloc 错误,因为第一个代码 sn-p 想要在参数列表中组装此字符串的位置分配大约 1.8GB,并且相应系统上没有足够的可用内存。 在我们将第二个代码 sn-p 中所见的字符串组装外包后,此错误不再发生。显然,这个字符串由 2 个整数和一个点组成,不需要任何接近 1.8GB 的​​空间。

如果有人能向我解释到底出了什么问题,我将不胜感激。我们怀疑它与一些黑色社会魔法相关的模板推导有关,但不确定。

【问题讨论】:

  • 来自soci.sourceforge.net/doc/master/binding "对象生命周期和不变性" 他们会警告您的问题。与类型推导无关,但与 soci::use 参数的生命周期无关。
  • 谢谢!这解释了它,非常感谢你:)

标签: c++ templates soci


【解决方案1】:

正如 Jarod42 所提到的,这个问题尤其与 soci::use 有关。 正如Soci Doku 提到的那样:

如果用户提供的数据来自另一个临时变量,编译器可能会以这样一种方式排列它们,即用户数据将在语句有机会执行之前被销毁,引用不再存在。

在这个解释之后出现了一个糟糕的示例(这大致是我的第一个不工作的代码示例),然后是类似于我的第二个(正确的)代码示例的东西。

因此,最后,第一个代码部分是如何不执行此操作的示例。 我写的错误来自访问未初始化的垃圾,因为在构建整个字符串之前,临时对象中的前两个字符串之一已经被销毁。在调试时也让我很困惑:使用 Clang 构建不会触发错误,而使用 Gcc 构建会触发错误。该文档也解释了这一点,因为问题与编译器相关的优化有关。

如果你使用 soci::use,你应该在调用函数之前组装临时对象,然后传递它们。无论如何,它可能更具可读性 - 但你必须知道它可能是错误的。

【讨论】:

  • “相关”以哪种方式?通过提供更多详细信息使答案有用。我认为这是关于对象生命周期的要求。
  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
  • 谢谢!我认为阅读 doku 已经足够清楚了,但是当我通过堆栈溢出搜索时,我也很欣赏一个好的书面答案 :) 我希望它现在更好!
猜你喜欢
  • 2017-07-06
  • 2013-11-14
  • 2021-10-14
  • 1970-01-01
  • 2011-03-31
  • 2016-12-02
  • 2016-05-08
相关资源
最近更新 更多