我有一个函数可以将 vsnsprintf 放入在堆栈上创建的对象的临时缓冲区中。
在对象的构造函数中,我将缓冲区的第一个字符初始化为空。
Valgrind 提示在 vfprintf.c 的堆栈上创建了一个未初始化的值
下面是完整的工作示例,后面是 valgrind 输出
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
struct tmp_buf
{
tmp_buf() { *b = 0; }
mutable char b[1024];
};
char const* va_stack_str(const char* format, va_list ap, const tmp_buf& b = tmp_buf())
{
vsnprintf(b.b, sizeof(b.b), format, ap);
return b.b;
}
char const* stack_str(const char* format, ...)
{
va_list ap;
va_start(ap, format);
const char* str = va_stack_str(format, ap);
va_end(ap);
return str;
}
int main()
{
printf("%s", stack_str("hello %s", "world"));
return 0;
}
该应用按预期工作,但通过 valgrind 运行它会提示未初始化的值
我的 valgrind 命令行是 valgrind --leak-check=full --track-origins=yes --quiet
Valgrind 输出:
==30513== Conditional jump or move depends on uninitialised value(s)
==30513== at 0x4E828F3: vfprintf (vfprintf.c:1661)
==30513== by 0x4E8B388: printf (printf.c:33)
==30513== by 0x400A73: main (main.cpp:28)
==30513== Uninitialised value was created by a stack allocation
==30513== at 0x4E80BF6: vfprintf (vfprintf.c:235)
==30513==
==30513== Syscall param write(buf) points to uninitialised byte(s)
==30513== at 0x4F233B0: __write_nocancel (syscall-template.S:81)
==30513== by 0x4EB0A82: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1261)
==30513== by 0x4EB1F5B: _IO_do_write@@GLIBC_2.2.5 (fileops.c:538)
==30513== by 0x4EB3ADD: _IO_flush_all_lockp (genops.c:848)
==30513== by 0x4EB3C39: _IO_cleanup (genops.c:1013)
==30513== by 0x4E730FA: __run_exit_handlers (exit.c:95)
==30513== by 0x4E73194: exit (exit.c:104)
==30513== by 0x4E58ECB: (below main) (libc-start.c:321)
==30513== Address 0x4025000 is not stack'd, malloc'd or (recently) free'd
==30513== Uninitialised value was created by a stack allocation
==30513== at 0x4E80BF6: vfprintf (vfprintf.c:235)
将 tmp_buf 构造函数更改为 memset 整个缓冲区不会更改 valgrind 的输出
tmp_buf() { memset(b, 0, sizeof(b)); }
最佳答案
虽然我对 Valgrind 不是很熟悉,但我可以在您的代码中看到一个明显的问题,并且可以就 Valgrind 以这种方式提示的原因提供我最好的猜测。
一、问题:
函数 va_stack_str 返回一个指向参数 b 的成员 b 的指针,它的类型是 const tmp_buf&。因为此函数无法控制此参数引用的对象的生命周期,所以它返回一个指针,其有效性只能在调用它的完整表达式结束之前得到保证。在参数 b 由临时初始化的情况下(这正是 stack_str 使用它的方式),那么完整表达式的结尾恰好是返回指针有效。
函数stack_str接着将va_stack_str返回的指针保存到局部变量str中,然后返回。此时,调用 va_stack_str 的完整表达式已经结束,因此指针悬空 - 它指向在堆栈上分配但已被释放的缓冲区。
代码之所以有效,可能是因为缓冲区确实存在的那部分堆栈在读取时没有被覆盖,因此仍然包含以前缓冲区的内容。
为什么我认为 valgrind 发出“未初始化值”警告:
vfprintf 肯定会为局部变量分配一些堆栈空间,其中一些可能分配在与我们要求它打印的缓冲区相同的堆栈内存中。当 vfprintf 然后使用这个缓冲区(我们传递给它的那个)时,Valgrind 认为这个内存不是我们的原始缓冲区(已被释放),而是 的局部变量的地址vfprintf 已分配。
我的猜测是这些局部变量之一在 vfprintf 扫描我们传递给它的缓冲区以寻找终止 NULL 字符时未初始化。在这种情况下,它会检查指向它自己未初始化的局部变量的内存,这通常不会发生,因为 vfprintf 稍后会在它打算使用它之前对其进行初始化。 vfprintf 期望您将传递一个指向您已分配的缓冲区的指针,而不是一个最终指向它自己的局部变量的指针!
关于c++ - Valgrind 报告标准库中未初始化的值 (vfprintf.c),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25883551/
在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到rubygems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调
我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc
我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我正在写一篇关于在Ruby中几乎一切都是对象的博客文章,我试图通过以下示例来展示这一点:classCoolBeansattr_accessor:beansdefinitialize@bean=[]enddefcount_beans@beans.countendend所以从类中我们可以看出它有4个方法(当然,除非我错了):它可以在创建新实例时初始化一个默认的空bean数组它可以计算它有多少个bean它可以读取它有多少个bean(通过attr_accessor)它可以向空数组写入(或添加)更多bean(也通过attr_accessor)但是,当我询问类本身它有哪些实例方法时,我没有看到默认
我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于