[置顶]VC2013的一个bug

前段时间在尝试使用一个C++的GUI库nana。这个库最大的特点在于使用现代C++风格去编写GUI程序,而不需要使用大量的比较丑陋的代码(如MFC中的各种宏),或者其它的非C++元素。这是一个比较新的库,作者是个中国人,有兴趣的朋友可以去试一试,由于使用大量的C++11特性,所以需要VC2013或者GCC4.7以上的编译器。使用过程中无意间发现了VC2013的一个重载决议(overload resolution)上的一个bug,这边贴出来跟大家分享一下,或许可以帮助大家少走点弯路。

我写了以下简单的代码来重现这个问题:

#include <iostream>
#include <string>

class foo{
public:
    void bar(std::string = {});
};

void foo::bar(std::string str)
{
    std::cout << str << std::endl;
}

int main()
{
    foo  f;
    f.bar();
}

编译运行这段代码,弹出一个错误:

按照错误提示,可以找到对应的代码1168行:

也就是这一行:

_DEBUG_POINTER(_Ptr);

加个断点可以发现这里面_Ptr为空指针,所以导致程序crash。这个问题其实比较容易理解,写一个更简单的例子就可以发现问题:

#include <string>

int main()
{
    std::string str = nullptr;
}

这段代码通过nullptr去初始化一个string,而这显然是错误的。

但问题在于,在最初的那段代码中,

void bar(std::string = {});

这个函数声明明明是给了函数bar一个默认参数,使其构造出一个空字符串。但为什么会调用xstring中的1168行呢?也就是参数为一个指针的assign函数呢?

经过多次试验以后发现,VC将上面这个声明理解为了:

void bar(std::string = {nullptr});

也就是用一个空指针去初始化一个string,从而导致了问题。同样的代码,在GCC4.8中是没有任何问题的。并且如果把

void bar(std::string = {});

改为:

void bar(std::string = std::string());

在VC2013里也没有问题了。这也就说明了VC2013在处理{}来初始化对象时的确存在重载决议的问题。

之所以之前说这个问题比较隐蔽,是因为这种情况只出现在类的成员函数中,如果是普通函数,就没有这个问题:

#include <iostream>
#include <string>

void func(std::string = {});

int main()
{
    func();
}

void func(std::string str)
{
    std::cout << str << std::endl;
}

上面这段代码和刚开始那段代码几乎一样,唯一的不同在于func是一个普通函数,而bar是一个成员函数。

不知道大家有没有遇到类似的问题?

本文由豆约翰博客备份专家远程一键发布

时间: 2024-10-12 03:59:46

[置顶]VC2013的一个bug的相关文章

[置顶]Win2012R2的一个Bug安装群集后可能引发的软件崩溃问题及相应补丁

如标题,笔者查阅资料发现微软声称安装故障转角色后就可能发生上述描述问题,但不止于SSMS崩溃.建议使用win2012R2的朋友安装补丁. 笔者在部署win2012R2+Sql2014 cluster时发现部署完成后,当使用SSMS创建新查询时,管理器就会崩溃.同时也发现win2012R2服务器管理器当打开本地管理器时也会发生ServerManager崩溃. 注:可能影响SSMS.exe,ServerManage.exe,devenv.exe等 发生崩溃视图-图1-1 图1-1 通过安装如下补丁可

VC2013的一个bug

前段时间在尝试使用一个C++的GUI库nana.这个库最大的特点在于使用现代C++风格去编写GUI程序,而不需要使用大量的比较丑陋的代码(如MFC中的各种宏),或者其它的非C++元素.这是一个比较新的库,作者是个中国人,有兴趣的朋友可以去试一试,由于使用大量的C++11特性,所以需要VC2013或者GCC4.7以上的编译器.使用过程中无意间发现了VC2013的一个重载决议(overload resolution)上的一个bug,这边贴出来跟大家分享一下,或许可以帮助大家少走点弯路. 我写了以下简

WPF 打开第三方程序并让程序窗口置顶

需要用到几个Win32函数: FindWindow GetWindowRect SetWindowPos //获取第三方程序窗口句柄 IntPtr hwnd = (IntPtr)Win32.FindWindow(null, "第三方程序窗口标题"); //获取窗口的位置和大小 Win32.GetWindowRect(hwnd, out rect); //设置窗口位置,第二个参数的意思是置顶,最后一个参数的意思是不可改变大小 Win32.SetWindowPos(hwnd, -1, re

WPF实现只打开一个窗口,并且重复打开时已经打开的窗口置顶

内容来自:https://codereview.stackexchange.com/questions/20871/single-instance-wpf-application 第一步:添加System.RunTime.Remoting引用 第二步:新建一个类class1.cs(按自己想法命名) using System; using System.Collections; using System.Collections.Generic; using System.ComponentMode

win8.1系统下,点击一个窗口,【当前活动窗口】该窗口无法置顶

两个或多个窗口同时显示在桌面的时候,点击下一层的窗口,无法置顶显示,无论怎么点击,还是隐藏在原置顶窗口的后面,只能手动把原置顶窗口最小化后,才能看到.例如,A窗口现在置顶,B窗口在A的后面,露出来一部分,我点击这一部分,A窗口的边框变灰,B窗口的边框变蓝,但是B窗口依然隐藏在A窗口后面,只能手动最小化A窗口,才能看到B窗口,然后这个时候,就是B窗口置顶了,接下来,我在在电脑下面的任务栏点击A窗口,A窗口同样无法置顶,还是显示在B窗口的下面,尽管B窗口的边框变成了灰色.

PullToRefreshListView设置标题置顶和下拉跟随

这几天想着界面的优化,关于PullToRefreshListView标题栏置顶和下拉跟随的效果.这里说说我的大体思路(如果你有跟好的方法,不吝赐教.)在listview的头部添加一个虚拟的headerView(跟标题一样)并设置成INVISIBLE.然后在下拉的时候隐藏标题栏,显示headerView. 首先看一下PullToRefreshBase的源码.这里是获得PullToRefreshListView下拉的距离(value). protected final void setHeaderS

Mysql数据库实现的简单置顶

Mysql数据库实现的简单置顶 1. 问题背景:小编要做一个文章管理的简单网页,用的是Mysql数据库.其中需要文章置顶功能,如图: 2. 最初的思路:机智的小编立刻大脑飞速运转,很快想到为存储文章的"article"表设定一个(int)型的"isTop"属性,0表示不置顶,大于0表示置顶且数字越大,优先级越高.显示的时候只需按照"isTop"降序显示.当用户需要将"id"为"001"的文章置顶时,后台只需

Universal-Image-Loader的一个BUG

使用UIL的内置圆角图片的功能时,发现一个BUG,就是它会拉伸图片,造成图片失真.费了一下午的功夫,重写了RoundedBitmapDisplayer,总算解决这个问题. 代码如下: public class RoundedBitmapDisplayer implements BitmapDisplayer { protected final int cornerRadius; protected final int margin; public RoundedBitmapDisplayer(i

iOS使用UIPageViewController结合多个UITableView后点击状态栏无法让UITableView置顶问题

页面结构:1个UIPageViewController含多个其他ViewController,每个ViewController中又包含了一个UITableView 问题:无法通过点击状态栏,让当前UITableView内容置顶 原因:UIPageViewController帮助我们管理了多个ViewController,本质上在UIPageViewController的view中包含多多个ViewController中的UITableView.由于每个UITableView的scrollsToT