Tag: c++

Entries for tag "c++", ordered from most recent. Entry count: 129.

Pages: 1 2 3 ... 17 >

20:08
Thu
30
Mar 2017

Microsoft Visual Studio 2017 - My Experience

Visual Studio 2017 came out recently. The list of news looks like it has been written by some marketing rather than technial guys. It starts with "Unparalleled productivity for any dev, any app, and any platform. Use Visual Studio 2017 to develop apps for Android, iOS, Windows, Linux, web, and cloud. Code fast, debug and diagnose with ease, test often, and release with confidence. You can also extend and customize Visual Studio by building your own extensions. Use version control, be agile, and collaborate efficiently with this new release!" - I've never seen so many buzzwords in just one paragraph.

Rest of the page is not different. They even call their installer "a new setup experience". They've also introduced "Lightweight Solution load", which is disabled by default - like everyone is assumed to prefer slower option :) Some other changes: "Visual Studio starts faster, is more responsive, and uses less memory than before." - that's unexpected direction. "Performance improvement: basic_string::operator== now checks the string's size before comparing the strings' contents." - wow, that's genius! They should file a patent for that ;) I hope they do the same for std::vector and other STL containers.

OK, but jokes aside, I've installed it on my personal PC, it installed quite fast and it works good. It preserved my settings, like the list of Include and Library Directories. Upgrade of my home projects went smoothly, without any problems.

There are many changes valuable for native code developers. What's New for Visual C++ in Visual Studio 2017 page mentions over 250 bug fixes, other compiler improvements and improved support for C++11, 14, and 17. I've already heard stories of programs running much faster after recompilation with this new compiler.

Contrary to what I thought before, Microsoft didn't abandon Graphics Diagnostics embedded into MSVS after they released new standalone PIX. They've actually added some new features to it.

So I definitely recommend upgrading to Visual Studio 2017. It is IMHO the best C++ IDE, and the new version is just next step in the right direction.

It seems that there is no new version of "Microsoft Visual C++ Redistributable Package" this time. Programs compiled with VS 2017 use VCRUNTIME140.DLL, just like in 2015 version.

Comments (0) | Tags: c++ visual studio | Author: Adam Sawicki | Share

19:39
Fri
09
Dec 2016

Operator New and Delete - Unnecessary Conditions

I've seen following constructs many times in C++ code:

MyClass* obj = new MyClass();
if(obj == nullptr)
    // Handle allocation error.

// ...

if(obj != nullptr)
    delete obj;

Both of these conditions are unnecessary. Strictly speaking they are not a bug - program will run correctly, but they make no sense. If you used to write any of these, you should know that:

1. Operator new doesn't return null on failed allocation. By default it throws an exception of type std::bad_alloc in this case, so this is what you should handle if you really care about the state of your program after it runs out of memory (or if the allocated object is particularly big).

There is also special nothrow version of the new operator that returns null on failure, but you must call it explicitly. An alternative would be to overload new operator (global or for particular class) to change its behavior. But again, this is not what happens by default.

Note this is different behavior than malloc function from C. Obviously there are no exceptions in C language, so this function just returns null on failure.

2. Operator delete doesn't crash when you pass null pointer to it - it just does nothing, so the check for not-null is already inside, you don't have to write it. Of course trying to delete object from any non-null address that was already freed or is just invalid address still crashes, or causes other undefined behavior.

Note this is the same behavior as free function from C - it also accepts null pointer.

Comments (0) | Tags: c++ | Author: Adam Sawicki | Share

16:43
Thu
28
Jul 2016

How to disable C++ exception handling using macros?

Some time ago my colleague showed me a clever way to disable exception handling in C++ using a set of preprocessor macros:

#define throw
#define try          if(true)
#define catch(...)   if(false)

Please note that:

So following code that uses exception:

try
{
    // Do something
    if(somethingFailed)
        throw std::exception("Message.");
}
catch(const std::exception& e)
{
    // Handle the exception.
}

Will resolve after defining these three macros to following:

if(true)
{
    // Do something
    if(somethingFailed)
        std::exception("Message.");
}
if(false)
{
    // Handle the exception.
}

Of course it's not a solution to any real problem, unless you just want your try...catch blocks to stop working. Disabling exception handling for real (and associated performance penalty, as well as binary code size overhead) is the matter of compiler options. And of course this trick makes errors not handled properly, so when an exception would be thrown, the program will just continue and something bad will happen instead.

But I think the trick is interesting anyway, because it shows how powerful C++ is (it empowers you to do stupid things :)

Comments (0) | Tags: c++ | Author: Adam Sawicki | Share

20:23
Sun
07
Feb 2016

How code refactoring can fix stack overflow error?

tl;dr: A very long C++ function with multiple local variables, even if they are not very big and they are placed in separate scopes, can reserve as much as hundreds of kilobytes of stack frame, causing "Stack Overflow" even without bugs like infinite recursion. So you better split your long functions into shorter ones.

Can refactoring (or the lack of thereof) cause application crashes? If we understand refactoring as changes in code layout without changing its logic, we might think that it's just the matter of readability and unreadable code increases chances of introducing bugs. But here is a story in which refactoring actually fixed a bug.

Long time ago in a software project far far away, there was a bug submitted telling that the application crashes with "Stack Overflow" message. It was a Windows app, developed in C++ using Visual Studio. I thought: - I can handle that, it should be easy! Every beginner/intermediate programmer knows about the call stack and surely seen this error at least once when accidentally caused infinite recursion in his code. So my first idea was that infinite recursion happens because of some logical error in the code (that should be easy to fix) or some unfortunate, invalid input data (that should be validated for safety before usage).

As it turned out, this was not the case. After setting up all the test environment and catching the crash in Visual Studio debugger, I looked at Call Stack and noticed that it looks quite normal. Sure the call depth was significant (as for C++, I'm not talking about Java here ;) and there was even some recursion, but 20 or 30 functions is not that much. The stack ended with a call to non-recursive function that seemed correct, so it was not the recursion that caused stack overflow.

My second idea was that some of these functions allocate some big objects (like arrays) by value, as local variables on the stack and this causes the stack to grow too big. I reviewed code of the functions that I found on the stack and used "Immediate Window" panel to quickly check sizeof(xxx) of variables or their types when they used some class, but I didn't find anything particularly big. Local variable sizes varied from few bytes to at most several hundred bytes and I couldn't find any big arrays defined in these functions. I also fetched address of some local variable in a function near the bottom of the stack (which looks like 0x000000000009a370), address of a parameter from the function at the top of the stack and subtracted them to see how big the stack grown over all these calls. The result was around 50 KB - not that much.

My third idea was to check maximum size of the stack. It is 1 MB by default, but it can be changed in Visual Studio project settings, in Linker > System tab, as "Stack Reserve Size" parameter. I check my project and I found this parameter not changed from its default value.

OK, now this became more difficult than I thought. After many debugging sessions, where I looked at various pointers, addresses and numbers trying to spot some memory override, stack corruption, out-of-bounds indexing etc., I finally opened "Disassembly" and "Registers" panels. I'm not a fan of such low level stuff, so it took me some time and few Google queries to understand these RSP, RBP registers and make sense of some x86-64 opcodes. While debugging step-by-step in the assembly, I found something interesting. At the beginning of my function, there was a call to mysterious function __chkstk and the crash occurred inside it. That was a clue I could use to ask Google what this all means. I found this: Description of the stack checking for Windows NT-based applications and this: What is the purpose of the _chkstk() function? These articles say that as the stack grows, next 4 KB pages are reserved. Each next page is allocated by the system on first "touch". I could actually see in my debugger that functions which need less than 1 page (4096 B = 1000h) have an instruction at the beginning similar to this:

sub         rsp,0A9h

While my debugged function had this instead:

mov         eax,26B29h
call        __chkstk (018104AA00h)
sub         rsp,rax

The articles say that when reserving more than one page of stack memory, this function must be called to loop over addresses with 4 KB step and "touch" each page. This is really what it does:

--- f:\dd\vctools\crt\crtw32\startup\amd64\chkstk.asm ---
sub         rsp,10h
mov         qword ptr [rsp],r10
mov         qword ptr [rsp+8],r11
xor         r11,r11
lea         r10,[rsp+18h]
sub         r10,rax
cmovb       r10,r11
mov         r11,qword ptr gs:[10h]
cmp         r10,r11
jae         cs10+10h (018104AA40h)
and         r10w,0F000h
lea         r11,[r11-1000h]
mov         byte ptr [r11],0
cmp         r10,r11
jne         cs10 (018104AA30h)
mov         r10,qword ptr [rsp]
mov         r11,qword ptr [rsp+8]
add         rsp,10h
ret

Key sentence of the second linked article seems to be: "The parameter in rax is size of data you want to add." In my case, eax is set to 26B29h = 158505. Wait, what?! This is more than 150 KB! Is it really how much of the stack the function needs?!

It was finally the right conclusion. The function was more than 3000-lines long, with lots of nested conditions and all kinds of stuff, but mostly an all-encompassing switch with dozens of different cases. I refactored it, extracting code from under each case to a separate function. This fixed the "Stack Overflow" crash.

Apparently if you have a long function and define a lot of local variables, even if they are not particularly big and they are placed inside separate scopes like if-s or switch case-s, the function may need as much as 150 KB of stack frame, at least in Debug configuration. This can cause crash with "Stack Overflow" message even without infinite recursion or bugs like that. So please keep this in mind as additional argument for refactoring your code as soon as you see the need for it.

Comments (2) | Tags: visual studio c++ | Author: Adam Sawicki | Share

18:00
Sat
05
Dec 2015

PrintStream 2.0 - Polymorphic Printf

Almost 4 years ago I shared a code snippet: CPrintStream - Polymorphic Printf. I recently came back to this code and decided to improve it in many ways. It is now more clean, efficient, and supports Unicode character set.

I created MISC repository on my GitHub for the purpose of such small code snippets and added new version of my code there, as:

GitHub sawickiap / MISC / PrintStream

Description:

A hierarchy of classes that represent abstract concept of a text-based stream that can be printed into, using methods like print(const char* str), printf(const char* format, ....) etc. Derived classes offer printing to console (standard output), to file, to memory buffer and more.

Comments (1) | Tags: c++ | Author: Adam Sawicki | Share

13:33
Sat
21
Nov 2015

type_safe_ptr - Idea for Type-Safe void* Pointer

I was thinking recently about passing raw data pointers (like void* or char*), which we have to do sometimes in C++. Is there any way to check if the type that we cast it to is the same as the type of last assigned value? I came up with an idea of implementing a "smart pointer" class using RTTI (specifically typeof operator) to store type information next to the actual pointer. Example usage:

int i = 123;
type_safe_ptr ptr{&i};
int j = *ptr.get_typed<int>(); // OK
float f = *ptr.get_typed<float>(); // Error

Initially I wanted to store pointer to const type_info struct returned by typeid operator, and it seems to work in Visual Studio 2015, but language standard defines the object returned by typeid as temporary, so it is not formally correct. Finally I decided to store typeid(T).hash_code(). You can find my implementation of classes type_safe_ptr and type_safe_const_ptr in file: type_safe_ptr.hpp. Here is example tesing program:

#include <cstdio>
#include "type_safe_ptr.hpp"

int main()
{
    type_safe_ptr ptr1;
    // ptr1 is null.
    assert(!ptr1);
    assert(ptr1.get() == nullptr);

    int i = 123;
    type_safe_ptr ptr2{&i};
    // ptr2 is pointer to int.
    assert(*ptr2.get_typed<int>() == 123);
    // It would activate assert inside type_safe_ptr.get_typed, because ptr2 is int not float.
    //assert(*ptr2.get_typed<float>() == 123.f);

    struct STest { int i; } obj;
    // itr2 is now pointer to STest.
    ptr2 = &obj;
    ptr2.get_typed<STest>()->i = 124;
    assert(obj.i == 124);
    // It would activate assert inside type_safe_ptr.get_typed, because ptr2 is now STest not int.
    //assert(*ptr2.get_typed<int>() == 123);
    
    type_safe_const_ptr cptr = type_safe_const_ptr(ptr2);
    // cptr is pointer to const STest.
    assert(cptr.get_typed<STest>()->i == 124);

    const int* constIntPtr = &i;
    cptr.reset(constIntPtr);
    // cptr is now pointer to const int.
    assert(*cptr.get_typed<int>() == 123);
}

Some issues and open question regarding my solution are:

Final question is, whether this whole idea of "type-checking void* smart pointer" makes any sense? I am not sure about that, but anyway it was a funny experiment :)

Comments (1) | Tags: c++ visual studio | Author: Adam Sawicki | Share

20:31
Wed
16
Sep 2015

Syntax of C++ Templates - Comparison

I noticed recently how C++ syntax differs when you define a class template, template instantiation, specialization or partial specialization. Here is an example:

// Template class definition.
template<typename T>
class Class1
{
public:
    void Print() { printf("Class1 template\n"); }
};

// Template class instantiation.
template
class Class1<int>;

// Template class specialization.
template<>
class Class1<double>
{
public:
    void Print() { printf("Class1 specialization for double\n"); }
};

// Template class partial specialization.
template<typename T>
class Class1<T*>
{
public:
    void Print() { printf("Class1 partial specialization for pointers\n"); }
};

Having these classes defined, following code fragment:

Class1<int> objInt;
objInt.Print();
Class1<double> objDouble;
objDouble.Print();
Class1<int*> objPointer;
objPointer.Print();

Produces following output:

Class1 template
Class1 specialization for double
Class1 partial specialization for pointers

Here is how the syntax can be compared:

Comments (3) | Tags: c++ | Author: Adam Sawicki | Share

22:10
Tue
15
Sep 2015

Unicode w Visual C++ - My Old Article

I just noticed that my old article "Unicode w Visual C++" (in Polish) was a dead link and restored it back online:

Unicode w Visual C++

It may not be "politically correct" if you believe in what they say in UTF-8 Everywhere manifesto, but I think the information that I have put there are still relevant and useful despite being 7 years old.

Comments (1) | Tags: c++ visual studio | Author: Adam Sawicki | Share

Pages: 1 2 3 ... 17 >

STAT NO AD [Stat] [Admin] [STAT NO AD] [pub] [Mirror] Copyright © 2004-2017 Adam Sawicki
Copyright © 2004-2017 Adam Sawicki