Archivo

Posts Tagged ‘Visual C++’

Beta de Visual Studio 11–29 de febrero


Pues bien, Soma Segar ha anunciado el primer beta de Visual Studio 11 y .NET 4.5 para el próximo 29. Y don Herb Sutter ya nos ha dado sus comentarios respecto a Visual C++. Resumiendo, algunas características interesantes:

  • Compatibilidad con el estándar C++ 11 prácticamente completado. Muchas cosas (como los lambdas) ya las tenemos desde VC++ 10, pero ahora sí estaremos completos. Esto es algo que se agradece de verdad.
  • Soporte para Windows 8 y Metro. Ya tendremos disponible C++/CX, el dialecto de Microsoft para trabajar con Metro. Cabe decir que éste es en realidad azúcar sintáctico, y que tras bambalinas el compilador genera código C++ y COM equivalente.
  • Windows Runtime Library. Una librería estilo ATL para que quienes no quieran usar C++/CX puedan interactuar con Metro sin necesidad de recurrir a COM directamente.
  • Soporte para paralelismo. Se liberan C++ AMP y el Parallel Patterns Library para trabajar con varios procesadores en pararlelo.
  • Mejoras en Intellisense y en el editor, algo de lo que sufrimos quienes usamos VC++; al parecer ¡ya nos van a poner al nivel de VC#!

También Visual C# trae cosas nuevas. Quizás lo mejor sea el soporte para programación asíncrona.

  • Soporte para realizar tareas asíncronas, incluídas en el lenguaje. El uso de “async” y “await” nos permite trabajar con tareas paralelas sin tener que meternos en multiárea. El colega Javier Torrecilla dio un muy buen webcast ayer mismo respecto a este tema.

Respecto al .NET Framework 4.5, algunas de als cosas interesantes que he encontrado son las siguientes.

  • Soporte en .NET para aplicaciones Metro. Obvio no podría quedarse atrás.
  • Mejoras en ASP.NET para soportar HTML 5 y CSS 3.0, soporte al protocolo WebSockets, lectura y escritura de las peticiones HTTP asíncronas.
  • En Windows Presentation Foundation ya tendremos un nuevo control: el Ribbon. Si bien es cierto que éste estaba disponible en Codeplex, ahora ya es parte integral del Framework.
  • Tras el fracaso que supuso quitar los flujos de trabajo de máquinas de estado en Windows Workflow Foundation, la nueva versión ya los volvió a implementar. ¡Enhorabuena! Esto ha hecho renacer mi interés por WWF.
  • Ah, y en la versión anterior de WWF se añadieron actividades que soportaban expresiones en VB, ahora soportan también expresiones en C#. ¡Uf!

También hay cosas para los desarrolladores de F#, muchas de ellas interesantes. Estas dos llamaron poderosamente mi atención.

  • Proveedores de tipos. Permiten generar tipos basados en datos estructurados, lo cual ayuda a acceder a fuentes de datos en bases de datos como SQL. Con esto, en mi opinión, F# da el gran paso de ser una herramienta académica a una herramienta de productividad en programas empresariales.
  • Expresiones de consulta, característica que implementa LINQ para F#. ¡Náaaaaaais!

¡Así que ya sabes, a descargar el beta!

Categorías:Noticias Etiquetas: , ,

Encuesta sobre Visual C++ 11, nuevas características y mis votos


En el blog del equipo Visual C++ ha aparecido una entrada en la que solicitan al mundo contestar una encuesta. Ésta hace referencia a aquellas características del nuevo estándar de C++ (llamado C++ 11) que queremos que el equipo de Visual C++ le de prioridad.

Como sabemos, algunas características de C++ 11 ya han sido incorporadas a Visual C++ 2010. Pero todavía faltan algunas otras, y Microsoft desea conocer nuestra opinión sobre a qué características darle prioridad.

Así que ya sabes: ¡participa! Aquí está la encuesta.

En mi caso, estas fueron las características que marqué como más urgentes.

1.- Delegating constructors. En C# podemos hacer esto:

class C
{
    string _param1;
    int _param2;

    C(string param1, int param2)
    {
        _param1 = param1;
        _param2 = param2;
    }

    C()
        : this(string.Empty, 0)
    {
    }
}

Esto rifa porque así creas un constructor genérico que puede ser invocado desde otros constructores. ¿No sería bueno contar con esto en nuestro Visual C++?

2.- Unicode literal strings. Para todos los que escribimos programas en otros lenguajes aparte del inglés, el mejorar el soporte para Unicode debería ser prioridad. Cierto, no sufrimos tanto como los chinos, árabes o hebreos, pero aún así debemos apoyar la causa: ¡por nuestro idioma!

3.- Use of char16_t y char32_t. Mismo razonamiento que el punto anterior, tratándose de tipos de dato para almacenar caracteres en Unicode (16 y 32 bits).

4.- Attributes. Similares a los atributos de C#:

// en C#
[WebMethod()] // este es un atributo
public void MyMethod()
{
}

El tener estos atributos en C++ nos ayudaría a olvidarnos de extensiones de compiladores como __declspec o __attribute__.

5.- Keyword exports. Aunque no es una opción, la puse en el punto 9, sobre comentarios adicionales.

La palabra reservada exports se utiliza cuando programamos clases plantillas. Hasta el momento, en Visual C++, tenemos que incorporar el cuerpo de nuestras funciones en la declaración de la clase. Intentarlo hacer por separado resulta en error de compilación.

Esta característica data del estándar C++ 98, si no me equivoco, pero Visual C++ nunca lo implementó. Y sé que no lo harán, menos ahora que el comité del estándar ha depreciado dicha palabra reservada (y la ha depreciado porque, salvo Comeau y Sun Studio, ningún otro compilador la implementó). Pero bueno, no se pierde nada con pedir.

Así que ya sabes, ¡vota por tus favoritas! ¡Participa!

Categorías:Noticias Etiquetas: ,

Cómo crear una aplicación MFC sin usar el wizard de Visual C++


Buenas noches entusiastas de la programación de C++. Hacía rato que no blogueaba de noche, así que heme aquí, retomando las buenas costumbres.

Afrontémoslo: C++ es el único lenguaje que obtiene todos los beneficios que ofrece Windows desde un inicio. Incluso C# y .NET tardan en acoplarse a las nuevas realidades. Para muestra, un botón: el famoso Ribbon del Fluent UI que se estrenó con Microsoft Office 2007, y que ha sido incorporado de forma nativa a Windows 7. Este elemento que hace vistosas nuestras interfaces gráficas para aplicaciones de escritorio llegó a nosotros a partir del Enhancement Pack de Visual Studio 2008 y viene incorporado de forma nativa en Visual C++ 2010. Sin embargo, no hay versiones oficiales, aunque hay muy buenos componentes por parte de terceros algunos, gratuitos como la versión del compatriota Menéndez Poo para Windows Forms o la versión que se distribuye con el WPF Toolkit en CodePlex para Windows Presentation Foundation. Sin embargo, aunque buenos, tienen el estigma de no ser oficiales de Microsoft.

Dicho esto, también hay que reconocer que la única forma para desarrollar aplicaciones con estas bondades en tiempos y costos razonables es necesario utilizar MFC. Ésta ha sido una gran herramienta, aunque su diseño, que data de 1991 las primeras versiones, es algo anticuado. Sin embargo, Qt aunque lejos todavía no ofrece todo lo que MFC en términos de componentes y otras librerías como wxWidgets o el impresionante Visual Component Framework del buen Jim Crafton les falta soporte general todavía, a mi parecer. Así que seguimos utilizando MFC, pese a todo.

Visual C++ es una gran ayuda para desarrollar con MFC, y está lleno de herramientas y asistentes para hacer el trabajo menos pesado. Pero seamos ciertos: a veces los asistentes generan mucho código basura. Esto es cierto en especial con Visual C++. ¿Recuerdan Visual C++ 6.0, que salió allá por 1998? El Class Wizard generaba tanta basura que era un dolor de cabeza terrible el mirar el código. Y es cierto, esto ha ido mejorando con cada nueva versión del IDE. En particular, he de decir que me siento mucho más cómo con la versión 2010 que con ningún otro entorno de desarrollo. Pero aún así los asistentes no son perfectos.

Tomemos como ejemplo el asistente de proyecto. Tantas opciones que hay: usar MDI, SDI, o tabs; soportar documento/vista, estilos visuales de Windows, MFC estándar, Internet Explorer, Visual Studio Office; usar barra de herramientas estándar, de navegación, Ribbon… en fin. Esto puede ser de gran ayuda, pero a veces el asistente genera tanta cosa que luego hay que pasarse horas limpiando todo para contar con un cascarón decente. Por ejemplo, el simple hecho de utilizar MFC genera infinidad de cadenas de texto en la tabla de cadenas del archivo de recursos, y usar el Ribbon hará que se generen decenas de imágenes, que luego uno tiene que editar y quitar.

WizardMFC

Así pues, a pesar de la ayuda que presta el asistente, a veces es mejor comenzar desde cero. Pero ¡oh sorpresa! A diferencia de los proyectos Win 32, cuyo asistente cuenta con la opción de “Proyecto vacío”, MFC no tiene nada de eso. Entonces, ¿cómo hacer para emular esto?

La solución radica en crear un proyecto nuevo para Win 32. En el asistente de proyecto nuevo, seleccionamos Win 32Project y dejamos las opciones por defecto.

NewProject

Cuando iniciemos, contamos con algunos archivos típicos: BlogTest.h (así se llama la aplicación que cree de ejemplo) no tendrá nada, Resource.h lo usa internamente el IDE, stdafx.h contiene algunos encabezados básicos y targetver tiene una llamada #include al archivo SDKDKVer.h. Por otra parte, stdafx.cpp tendrá un #include “stdafx.h” y será nuestro archivo precompilado, y BlogTest.cpp contendrá la función WinMain. Bien, pues ahora sí, manos a la obra. Lo primero a hacer es eliminar el fastidioso ReadMe.txt.

Acto seguido, necesitamos indicarle al compilador que vamos a trabajar con MFC, así que nos vamos al menú Project y seleccionamos la opción Propiedades de proyecto. En la ventana que nos aparece, expandimos el árbol de “Propiedades de configuración” y nos vamos al nodo “General”. En las propiedades, buscamos la que dice “Uso de MFC” y establecemos el valor a “Usar MFC en librería compartida”. Le damos clic al botón “Aplicar” y repetimos los pasos ahora para la configuración de “Release”.

ProjectProperties

Ya que hicimos estos pasos, estamos listos para utilizar MFC. Necesitaremos a continuación comenzar a escribir código a manita, y mi recomendación sería por comenzar a limpiar los archivos con los que contamos. Comencemos por stdafx.h. En primer lugar, nos deshacemos de los comentarios, dejamos el #include hacia targetver.h y reemplazamos los #includes hacia los archivos de Windows con los de MFC. Al final, deberías tener algo como esto:


#pragma once

#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN            
#endif

#include "targetver.h"

#include <afxwin.h>
#include <afxext.h>
#include <afxdtctl.h>
#include <afxcmn.h>  
#include <afxcontrolbars.h>
#include <afxwinappex.h>
#include <afxdialogex.h>

Luego nos vamos a targetver.h. Este archivo se usa para definir las versiones de Windows que planeamos soportar. En Visual C++ 2008 el asistente generaba algunos símbolos, que ahora han sido reemplazados por un archivo que viene dentro del SDK de Windows, llamado sdkdkver.h. Lo único que tenemos que hacer, pues, es definir el símbolo _WIN32_WINNT con la versión mínima de Windows que queremos soportar y luego dejar el include a sdkdkver. Si no añadimos nada, por defecto asumirá soporte para Windows 7. En mi caso, me gustaría que el soporte mínimo fuera para Windows Vista, por lo que mi targetver.h luce así:


#pragma once

#define _WIN32_WINNT	0x0600

#include <sdkddkver.h>

Perfecto. Resource.h se usa de forma interna, por lo que de momento lo dejamos de lado y pasamos a BlogTest.h. Dado que comenzamos con un proyecto Win32, no habrá nada, pero como sabes para iniciar una aplicación MFC necesitamos crear una clase derivada de CWinApp ó CWinAppEx e instanciarla en algún objeto global. Bien, pues manos a la obra. Creamos dicha clase que debe incluir por lo menos la sobrecarga de InitInstance y ExitInstance. Alternativamente podemos sobreescribir OnAppAbout y de requerirse, PreLoadState, LoadCustomState y SaveCustomState. En mi ejemplo mantendré éstas tres últimas, aunque no hagan nada.

#pragma once

class CBlogTestApp : public CWinAppEx
{
    DECLARE_MESSAGE_MAP();

    public:
        CBlogTestApp();
        virtual ~CBlogTestApp();

        virtual BOOL InitInstance();
        virtual int ExitInstance();

        virtual void PreLoadState();
        virtual void LoadCustomState();
        virtual void SaveCustomState();

        virtual void OnAppAbout();
    
};

extern CBlogTestApp g_objApp;

Bien, ya terminamos nuestros encabezados, vamos ahora con los archivos de implementación. Primero, limpiamos stdafx.cpp de los comentarios y dejamos solo el #include “stdafx.h”. Pasamos ahora al BlogTest.cpp y borramos todo lo que haya. Y a escribir se ha dicho.

  1. Primero, incluimos los archivos de cabecera stdafx.h, resource.h y blogtest.h. Creamos el constructor (donde establecemos si queremos utilizar el Restart Manager que viene con MFC 10, y el ID de nuestra aplicación), el destructor y el mapa de mensajes, que dejaremos con las opciones tradicionales para el AppAbout, Archivo nuevo, Abrir archivo e Imprimir. Luego, instanciamos nuestro objeto global.
  2. Segundo, escribimos el método InitInstance. Tendremos que inicializar los controles comunes, llamar a la versión base de CWinAppEx, inicializar OLE, inicializar cuestiones avanzadas de la interfaz gráfica y establecer las llaves del registro de Windows donde se guardarán nuestras configuraciones. Nota que como de momento no usamos una ventana  o un diálogo ni nada, no incluimos las llamadas al parseo de la línea de comandos o del shell, ni el registro del documento, la vista y el marco hijo (arquitectura documento/vista) ni nada, pero eventualmente necesitaremos añadir el soporte, según veamos necesario.
  3. Finalmente, escribimos el OnAppAbout, el ExitInstance y demás métodos que tengamos.

He aquí el código.


#include "stdafx.h"
#include "Resource.h"
#include "BlogTest.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CBlogTestApp::CBlogTestApp()
{
	m_dwRestartManagerSupportFlags = 
        AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
	SetAppID(_T("Fermasmas.BlogTest.BlogTest.1"));
}

CBlogTestApp::~CBlogTestApp()
{
}

BEGIN_MESSAGE_MAP(CBlogTestApp, CWinAppEx)
	ON_COMMAND(ID_APP_ABOUT, &CBlogTestApp::OnAppAbout)
	ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
	ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
	ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
END_MESSAGE_MAP()

CBlogTestApp g_objApp;

BOOL CBlogTestApp::InitInstance()
{
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinAppEx::InitInstance();

	if (!AfxOleInit())
	{
		AfxMessageBox(_T("Init failed"));
		return FALSE;
	}

	AfxEnableControlContainer();
	EnableTaskbarInteraction();

	SetRegistryKey(_T("Fermasmas Blog Test"));
	LoadStdProfileSettings(5);  

	InitContextMenuManager();
	InitShellManager();
	InitKeyboardManager();

	InitTooltipManager();
	CMFCToolTipInfo ttParams;
	ttParams.m_bVislManagerTheme = TRUE;
	g_objApp.GetTooltipManager()->SetTooltipParams(
        AFX_TOOLTIP_TYPE_ALL, 
        RUNTIME_CLASS(CMFCToolTipCtrl), 
        &ttParams);

	return TRUE;
}

int CBlogTestApp::ExitInstance()
{
	AfxOleTerm(FALSE);

	return CWinAppEx::ExitInstance();
}

void CBlogTestApp::OnAppAbout()
{
	AfxMessageBox(_T("Fermasmas BlogTest 1.0"));
}

void CBlogTestApp::PreLoadState()
{
}

void CBlogTestApp::LoadCustomState()
{
}

void CBlogTestApp::SaveCustomState()
{
}


Ahora ya está todo listo, y aunque nuestra aplicación no hace nada ya tenemos una aplicación funcional. O casi. Si compilamos, seguramente tendremos una advertencia de compilación que nos dice que IDC_STATIC ya ha sido redefinido. Esto pasa porque el archivo de recursos que el asistente de Win32 nos genera está pensado para proyectos Win32 y no MFC. Necesitamos editar este archivo. Así que primero, abrimos Resource.h. Necesitamos eliminar la línea con el símbolo de que no se soporta MFC: _APS_NO_MFC. Y luego, eliminar la definición de IDC_STATIC. Al hacerlo, quedaría así:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by BlogTest.rc
//

#define IDS_APP_TITLE            103

#define IDR_MAINFRAME            128
#define IDD_BLOGTEST_DIALOG    102
#define IDD_ABOUTBOX            103
#define IDM_ABOUT                104
#define IDM_EXIT                105
#define IDI_BLOGTEST            107
#define IDI_SMALL                108
#define IDC_BLOGTEST            109
#define IDC_MYICON                2
//#ifndef IDC_STATIC
//#define IDC_STATIC                -1
//#endif
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

//#define _APS_NO_MFC                    130
#define _APS_NEXT_RESOURCE_VALUE    129
#define _APS_NEXT_COMMAND_VALUE        32771
#define _APS_NEXT_CONTROL_VALUE        1000
#define _APS_NEXT_SYMED_VALUE        110
#endif
#endif

Y ahora sí, abrimos el archivo de recursos desde el editor de código. Lo primero que notamos es que en las líneas 13-15 se hace referencia a los archivos de Windows. Mala cosa, necesitamos cambiarla por referencias a MFC. Además, necesitamos añadir la referencia a los recursos de MFC estándares y para el Ribbon y demás cosas. Sin embargo, tenemos el pequeño problema de que si sobreescribimos este archivo, Visual C++ se encargará amablemente de regenerarlo como estaba antes. Patatús.

Si nos vamos a las líneas 102-130, veremos algo como lo que sigue.

#ifdef APSTUDIO_INVOKED
///////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#ifndef APSTUDIO_INVOKED\r\n"
    "#include ""targetver.h""\r\n"
    "#endif\r\n"
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""windows.h""\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

Esto, señoras y señores, es el texto con lo que Visual C++ generará en automático. Como ves, aquí tenemos los #define’s e #include’s a cosas de windows.h, por lo que vamos a reemplazarlo por los #include’s a los archivos de MFC. Algo así debería quedar ese bloque.

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#ifndef APSTUDIO_INVOKED\r\n"
    "#include ""targetver.h""\r\n"
    "#endif\r\n"
    "#include ""afxres.h""\r\n"
    "#include ""verrsrc.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "#define _AFX_NO_OLE_RESOURCES\r\n"
    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
    "\r\n"
    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
    "LANGUAGE 9, 1\r\n"
    "#include ""afxres.rc""      // Standard components\r\n"
    "#include ""afxprint.rc""    // printing/print preview resources\r\n"
    "#if !defined(_AFXDLL)\r\n"
    "#include ""afxribbon.rc""  // MFC ribbon and control bar resources\r\n"
    "#endif\r\n"
    "#endif\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED

El primer bloque queda como está. En el segundo, cambiamos la referencia a windows.h  por la de afxres.h y añadimos versrc.h. El tercer bloque contiene #include’s al archivo de recursos estándar (afxres.rc), a uno para soporte para impresión (afxprint.rc) y otro más para el Ribbon (afxribbon.rc). Una vez que hayamos hecho este cambio, guardamos y cerramos los archivos de recursos, y lo abrimos nuevamente desde la vista de recursos en el IDE. En cuanto hagamos desde ahí algún cambio y guardemos el archivo, Visual C++ lo regenerará con la nueva información.

NOTA: es posible que al intentar abrir la vista de recursos te mande un error, diciendo que IDC_STATIC no está definido. Sucede que seguramente en el archivo de recursos tienes la definición para una ventana de diálogo que contiene el “Acerca de”. Y como eliminamos la definición de IDC_STATIC y el archivo de recurso todavía no se ha generado con los nuevos #include’s pues el IDE protestará. No problemo. Editamos el archivo de recurso y comenta todas las referencias a IDC_STATIC –ya luego las agregarás de nuevo.

Bueno pues, ahora sí tenemos nuestra solución lista para ser desarrollada. Si vas a hacer alguna aplicación basada en diálogos, crea tus clases derivadas de CDialog o CDialogEx y haz el DoModal desde el InitInstance de tu clase derivada de CWinAppEx. Si vas a utilizar una ventana con soporte SDI/MDI/TDI, ya sabes: a derivar de CFrameWndEx / CMDIFrameWndEx, CChildFrameEx / CMDIChildFrameEx, etc., así como de CDocument y CView y hacer todo lo que uno hace.

Conclusiones a las dos de la mañana:

  1. C++ sigue siendo la única forma de acceder a las últimas características que ofrece Windows de forma natural, y MFC la única forma comercialmente viable de desarrollar con C++ para Windows.
  2. Visual C++ cuenta con asistentes para facilitar el desarrollo en MFC, pero a veces puede ser un Pain In The Ass® por todo el código y archivos adicionales que le mete, de tal suerte que podemos pasar mucho tiempo limpiando nuestro código.
  3. Existe una forma de solucionar lo anterior, aunque implica escribir algo de código a manita, lo cual sigue siendo mejor que limpiar lo generado por el asistente. Esta forma consiste en crear un proyecto para Win32, agregarle soporte para MFC en las propiedades del proyecto, cambiar el WinMain por una clase derivada de CWinApEx y ajustar los archivos de recursos.
  4. En adelante, lo que queda es derivar las clases que vamos a usar y en general construir nuestra aplicación.

Bueno jóvenes, eso ha sido todo por hoy. Espero que le encuentre utilidad. Ciao bambini!

 

Post Scriptum. Desde hace mucho tiempo he tenido la intención de escribir un tutorial de MFC. El problema es que hacer algo así es algo monumental que lleva mucho tiempo, por lo que no me he decidido a dar el paso. Pues bien, este artículo quizás sirva de base para comenzar. Quién sabe, ya veremos. Pero antes necesito saber: ¿creen que sería bueno hacer el tutorial, o con los que ya existen tenemos? Espero sus comentarios. 

Categorías:C++, Cómo hacer, WIN-32 Etiquetas: ,

Mirada al Visual C++ 2010


En estos días Jonathan Wood creó un video en el que hace un sumario rápido sobre las nuevas características de Visual C++ 2010. El vídeo aquí.

El vídeo resulta interesante, desde luego. En éste, Wood afirma que Microsoft ha decidido retomar el camino del código nativo y su plataforma Win32 – MFC. Se muestra complacido con ello, y comenta que los principales cambios son a la librería MFC así como al lenguaje mismo.

Las siguientes son las nuevas características.

  1. Mejoras a la librería MFC. Estas incluyen la incorporación de diversos controles como el Ribbon de la Fluent UI de Microsoft Office, mejores barras de herramientas, controles como botones con imágenes y cajas de texto con botón incluido, paneles adheribles, barra de Outlook y muchos más.
  2. Un diseñador para poder crear Ribbons. Así como diseñamos menús o barras de herramientas, ahora podemos diseñar ribbons.
  3. Un manejador de estilos para que el tema de la ventana se vea normal, como el de Office (en azul, negro, gris), como el de Visual Studio o como el de Windows 7.
  4. MFC Restart Manager. Un administrador para que las aplicaciones se recuperen (y recuperen documentos) cuando una aplicación se termina inesperadamente, guardando el documento sin salvar. Similar a como funciona Word o Visual Studio.
  5. El class wizard ha regresado.
  6. Nueva clase: CTaskDialog que se puede utilizar en lugar de los mensajes comunes disparados con AfxMessageBox. Solo funciona para Windows Vista en adelante.
  7. Actualizaciones al lenguaje C++: deducción de tipo de dato (“auto”), obtención del tipo de dato de una expresión (“decltype”), funciones lambda, referencias a un r-valor (valor asignado), puntero nulo (“nullptr”)

Aunque los avances presentados son importantes, también hay cosas que decir al respecto. En mi opinión:

  1. Las mejoras a MFC son importantes desde luego. El ribbon y demás componentes del Fluent UI son aire fresco para MFC, que no había sufrido una actualización significativa desde MFC 6.0. Además pone a MFC como la única plataforma de desarrollo soportada por Microsoft para desarrollar con el Fluent UI (ni Windows Forms ni Windows Presentation Foundation lo soportan). Pero estas actualizaciones salieron en el Visual C++ 2008 Feature Pack. Es decir, ya estaban disponibles como instalación aparte del VC2008, y para el 2010 solo las distribuyen “out-of-the-box”. Así que en otras palabras, ésto no es algo nuevo.
  2. El diseñador de ribbons está supremo. Antes era muy complicado ir creando los ribbons, con este diseñador la verdad que sí se lucieron estos tíos. ¡Gracias y enhorabuena!
  3. El manejador de estilos no es nuevo, también viene con el Feature Pack antes mencionado. Pero sí lo actualizaron para incluir el tema de Windows 7, lo cual es bueno, porque además soportan el utilizar el ribbon de Windows 7 (aquel que viene cuadradito, más minimalista, que se puede ver en mspaint o wordpad de W7).
  4. El Restart Manager de MFC supone un gran alivio cuando uno tiene que recuperar documentos. Un servicio más para nuestros usuarios de forma fácil.
  5. El class wizard nunca debió irse en primer lugar. En lo personal no me gusta utilizarlo, pero sé que hay mucha gente que sí lo utiliza. Luego entonces nunca debió desaparecer.
  6. Con Visual C++ 2008 podíamos utilizar un control nativo de Vista para hacer esto. Esta clase encapsula de mejor forma dicho control y lo hace extremadamente útil, ya que al usuario hay que proveerlo con mucha información cuando tiene que hacer decisiones importantes. Buen punto.
  7. Estas actualizaciones no son otra cosa que la incorporación de algunos puntos de C++0x. Está bien que lo hagan, pero el draft de C++0x todavía no queda completamente aprobado, así que tendremos que esperar a otra liberación de Visual C++ para poder tener la versión final de la nueva versión de C++. Sin embargo, bienvenido sean “auto” y “decltype” ya que ayudarán mucho en lo que a MFC se refiere.

Al final me parece que Visual C++ todavía queda a deber. Es cierto que el Feature Pack es algo muy bueno, solo que es una lástima que sigan sin cambiar muchas cosas de MFC que tienen pendientes. En lo personal me gustaría ver una buena librería para utilizar servicios web (sé que existe la Windows Web Services API pero me gustaría ver más integración con Visual C++) y una buena librería para XML (sé que existe MS-XML como componentes COM, pero distan mucho de ser fácilmente utilizables). ¿O qué tal mejorar las clases de ODBC para quitarle varias de las limitantes que tienen? Además muchos de las nuevas características son refritos del Feature Pack. Y por no mencionar que quitaron el soporte ISAPI para desarrollar sitios web con C++, ATL Server. Ojalá lo vuelvan a habilitar.

Pero al menos vamos por buen camino. Espero fervientemente que para la próxima versión Microsoft siga impulsando el desarrollo nativo, de la misma forma en que lo hacía cuando salió Visual C++ 6.

Categorías:C++, Noticias, Visual Studio Etiquetas:

Cómo detectar fugas de memoria con Visual C++


Fugas de memoria (memory leaks), cosas horribles del mundo, uno de los más grandes enemigos a los que el programador de C++ se puede enfrentar.

Todos las conocemos, ¿verdad? Ubicas memoria dinámica y olvidas desubicarla:

int main()
{
  int* p = new int();

  return 0;
  // no se elimina p con un delete, así que
  // aquí hay una fuga de memoria
}

 

Obvio el caso anterior difícilmente ocurriría en la vida real. Era un ejemplo simple. En esa vida real cosas mucho más complicadas pueden ocurrir. Y encontrar en dónde se encuentra la fuga es una tarea titánica.

Visual C++ provee algunas herramientas para poder detectar fugas de memoria. Cuando corremos nuestro programa en modo de depuración.

En primer lugar, cuando trabajamos con ATL o MFC, tenemos una macro llamada DEBUG_NEW que sirve para dar información sobre el archivo y línea donde se invoca la creación dinámica. Para ello tendríamos que hacer algo como:

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

e incluirlo en todos los archivos. DEBUG_NEW lleva un registro de todos los objetos creados de forma dinámica, con el nombre del archivo y la línea de donde fueron instanciados. Cuando el programa termina, se llama al Object Dump de todos los objetos (en el caso de aquellos que deriven de CObject, se manda a la versión de CObject::Dump), lo que hace que se muestre información en la ventana de "Output" del IDE de Visual C++. Cuando hay un memory leak, así se presentará.

memoryleak

En la figura anterior les pongo un ejemplo. Corrí mi programa y al cerrarlo me detectó una fuga de memoria. En el output podemos ver los "dumps" o volcado de memoria que hace el IDE (en mi caso, Visual C++ 9). En particular, notamos que el primer volcado me lo redirecciona al archivo lookupoptions.cpp. Esto es gracias a que emplée DEBUG_NEW como indiqué anteriormente. Por ello, al hacer doble click me lleva directamente a donde se ubicó el elemento.

Por supuesto el saber dónde se generó el objeto es una parte del problema. Pero no siempre resulta obvio. Por ejemplo, en la figura anterior se crea un objeto con new y se agrega a una colección. Ésta se usa a lo largo de la existencia de una ventana hija y posteriormente la colección se encarga de eliminar todos los objetos que contenga. Por lo que la eliminación del objeto está en otra parte del código, posiblemente sin estar relacionada. Si el problema no es ubicar el objeto en memoria, sino desubicarlo.

Para poder detectar esto, normalmente tenemos que saber bajo qué condiciones se está creando nuestro objeto. En el ejemplo anterior, el IDE marca la clase que genera el objeto, pero no marca bajo qué condición se crea (i.e. qué otro objeto mandó crear la colección antes mencionada). ¿Cómo podríamos saberlo? Un breakpoint sería buena opción. Pero mejor aún, un breakpoint bajo las condiciones en las que se da la fuga. Pues bien, MFC / Visual C++ provée un mecanismo para hacer esto.

Cada objeto que se crea de forma dinámica tiene un ID, que representa su número de creación. Cuando se hace el volcado de la memoria para detectar la fuga, se imprime este ID entre llaves. En la figura anterior se muestran encerradas en un círculo rojo. En este caso, el objeto fue el 27620° en ser creado. Por otro lado, existe una función, _CrtSetBreakAlloc que toma como parámetro un número que es precisamente el número de objeto creado (en el caso del ejemplo anterior, 27620). Esta función hace que cuando se vaya a crear el objeto cuyo número es el del parámetro (i.e. 27620) se mande llamar a AfxDebugBreak, lo cuál actúa como un breakpoint. En ese momento, podemos revisar el stack y demás variables para saber cuál es el entorno y contexto de la creación de mi objeto, facilitando la caza del bug.

Luego entonces, basta mandar llamar a _CrtSetBreakAlloc al mero inicio del programa (main si estamos en consola, WinMain si es una aplicación para Windows, y CWinApp::InitInstance si trabajamos con MFC.

Me pareció interesante, ya que recientemente tuve este problema y pude resolverlo de forma fácil así. MSDN tiene éste artículo que viene con técnicas más avanzadas para detectar fugas de memoria, y éste artículo que habla sobre lo que les acabo de comentar.

Espero esto ayude a eliminar esas cosas horribles llamadas Fugas de Memoria.

Categorías:C++, Cómo hacer, Visual Studio Etiquetas: