前段时间在尝试使用一个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是一个成员函数。

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

VC2013的一个bug的更多相关文章

  1. [置顶]VC2013的一个bug

    [置顶]VC2013的一个bug 前段时间在尝试使用一个C++的GUI库nana.这个库最大的特点在于使用现代C++风格去编写GUI程序,而不需要使用大量的比较丑陋的代码(如MFC中的各种宏),或者其 ...

  2. Tomcat一个BUG造成CLOSE_WAIT

    之前应该提过,我们线上架构整体重新架设了,应用层面使用的是Spring Boot,前段日子因为一些第三方的原因,略有些匆忙的提前开始线上的内测了.然后运维发现了个问题,服务器的HTTPS端口有大量的C ...

  3. MySQL关于exists的一个bug

    今天碰到一个很奇怪的问题,关于exists的, 第一个语句如下: SELECT ) FROM APPLY t WHERE EXISTS ( SELECT r.APPLY_ID FROM RECORD ...

  4. 由一个bug引发的SQLite缓存一致性探索

    问题 我们在生产环境中使用SQLite时中发现建表报“table xxx already exists”错误,但DB文件中并没有该表.后面才发现这个是SQLite在实现过程中的一个bug,而这个bug ...

  5. Win10系统菜单打不开问题的解决,难道是Win10的一个Bug ?

    Win10左下角菜单打不开,好痛苦,点击右下角的时间也没反应,各种不爽,折磨了我好几天,重装又不忍心,实在费劲,一堆开发环境要安装,上网找了很多方法都不适用.今天偶然解决了,仔细想了下,难道是Win1 ...

  6. 你可能不知道的 NaN 以及 underscore 1.8.3 _.isNaN 的一个 BUG

    这篇文章并不在我的 underscore 源码解读计划中,直到 @pod4g 同学回复了我的 issue(详见 https://github.com/hanzichi/underscore-analy ...

  7. 标准模板库(STL)的一个 bug

    今天敲代码的时候遇到 STL 的一个 bug,与 C++ 的类中的 const 成员变量有关.什么,明明提供了默认的构造函数和复制构造函数,竟然还要类提供赋值运算符重载.怎么会这样? 测试代码 Tes ...

  8. 是uibutton跟tableviewcell同步使用一个bug

    这个问题是uibutton跟tableviewcell同步使用一个bug,不关delay一点毛事,证据就是点击事件没问题,so,搜到一个方法解决了这个问题.uibutton分类symbian2+ios ...

  9. 在chrome下-webkit-box布局的一个bug

    chrome,也就是webkit内核下作的检测, chrome版本是40, -webkit-box这种布局在移动端用的比较多,主要是因为pc端的浏览器内核参差不齐. 因为在写HTML的时候看上了-we ...

随机推荐

  1. android定位GPS定位 代码实现

    package com.lx.util;   import android.content.Context; import android.content.SharedPreferences; imp ...

  2. AsyncTask实现多任务多线程断点续传下载

    这篇博客是AsyncTask下载系列的最后一篇文章,前面写了关于断点续传的和多线程下载的博客,这篇是在前两篇的基础上面实现的,有兴趣的可以去看下. 一.AsyncTask实现断点续传 二.AsyncT ...

  3. JAVA中取子字符串的几种方式

    有这样一串字符串:String s = "共 100 页, 1 2 3 4..."; 假如我想把"100"给取出来,该如何做? 方法一: 采用split的方式 ...

  4. 用Java实现约瑟夫环

    约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重 ...

  5. Ext JS 6 新特性和工具

    Ext JS 6 新特性和工具 Ext JS 6 带来很多新特性.工具和改进.以下是一些亮点: • 合并了 Ext JS & Sencha Touch - 在 Ext 6, 你可以访问 Ext ...

  6. algo_预备

    章 C + +程序设计 大家好!现在我们将要开始一个穿越" 数据结构.算法和程序" 这个抽象世界的特殊旅程,以解决现实生活中的许多难题.在程序开发过程中通常需要做到如下两点:一是高 ...

  7. C#实现IDispose接口

    .net的GC机制有两个问题:首先GC并不能释放所有资源,它更不能释放非托管资源.其次,GC也不是实时的,所有GC存在不确定性.为了解决这个问题donet提供了析构函数 public class Te ...

  8. Android之 -WebView实现离线缓存阅读

    前言 本篇博客要实现的是一个离线下载和离线阅读的功能,这是很多阅读类app都常见的一个功能,典型的应用就是网易新闻.什么是离线下载?其实这个概念是比较模糊,是离线之后下载呢,还是下载之后离线,但稍微有 ...

  9. 2015 Android Dev Summit(安卓开发峰会)第一天

    今年的Google I/O没有抽到票,不能到现场参加.不过11月举行的Android Dev Summit的票是先到先得的方式,所以早早的提交了注册.今天终于有机会当面跟Android系统的设计开发者 ...

  10. C# 调用百度地图Web服务API

    最近公司项目中需要根据两个地点的交通路径和距离做一些数据推荐,为了程序的稳定和用户体验所以想从百度地图 API 采集数据保存到数据库中,经过一翻研究之后选定了百度地图 Web 服务 API 中的 Di ...