| Richard's profileRichard RudekPhotosBlog | Help |
Richard Rudek |
|||||
|
December 31 The symbols you have when you don’t have symbolsI had a problem the other day where I could not set any breakpoints on code which, at first glance, appeared to have the appropriate debugging symbols. It was especially annoying when I recompiled the code, yet could still not set any breakpoints on the code I just compiled. I’ll first show how I confirmed the cause of the problem, then I’ll show this can be reproduced. The cause is actually quite simple – it really didn’t have the required symbols, despite the fact that the PDB matched the DLL in question. For example, here’s what my reproduced sample, PdbTest01, does during a debugging session in Visual Studio 2005sp1/vista (an executable rather than a DLL, but the problem manifests the same way): Here’s what happens using WinDBG: Yet the symbols also appear to be loaded: 0:000> lmm pdbtest01 start end module name 00400000 00405000 PdbTest01 (private pdb symbols) d:\symbols\PdbTest01.pdb\...\PdbTest01.pdb InvestigatingWhat we need is a tool that lets us examine what’s actually in the PDB. Thankfully, a free tool for this already exists – the Debugging Tools for Windows includes a utility named DBH, and it’s elines command can enumerate all of the source-code lines contained within the symbols file. It’s a command-line tool, and here is a portion of it’s output when run against the appropriate PDB: C:\Users\Richard>dbh D:\DEVELOP\Tinkering\release\PdbTest01.pdb
PdbTest01 [1000000]: elines
OBJ:.\release\PdbTest01_Lib.obj
d:\develop\tinkering\pdbtest01_lib\pdbtest01_lib.cpp
24 25 26
...
Now I suppose I should first explain that the executable being examined here (PdbTest01.exe) is a Windows Console-mode program, and it’s built from a ‘main’ source file (PdbTest01.cpp), and a static Library (PdbTest01_Lib.LIB). See the next section for the details. Clearly from the output of the elines command shown above, there’s only one (user-supplied) object file that contains (debugging) source lines, and this object file came from the static Library. That is, you can see that there is a pdbTest01_Lib.obj, which was built from a pdbtest01_lib.cpp source file, and we have lines 24, 25 and 26 from that cpp file. We do not have any source lines from the PdbTest01.cpp (no _Lib in the name). That’s the clear indicator. Simple, eh ?
ReproducingI first stumbled across this odd situation whilst working on some old source code using Microsoft Visual Studio 6.0. But for the reproduction, here, I’m going to use Visual Studio 2005sp1/vista. The trick here is that we need to produce at least two object files, but only one of those, the static library, will be built with symbols. The object file for the main executable is configured not to produce symbols (debug Info). Add two C++ projects to a solution: a Windows Console app and a static library. The static library consists of two files (well four if you count the pre-compiled header stuff): a library header and a cpp file. Here is the source for the header file, PdbTest01_Lib.h (single line):
and here’s the source for the static library’s cpp file, PdbTest01_Lib.cpp: #include "stdafx.h" #include "PdbTest01_Lib.h" int Func1() { return 1; } Now here’s the source for the main executable, PdbTest.cpp: // PdbTest01.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <conio.h> #include "..\PdbTest01_Lib\PdbTest01_Lib.h" int _tmain(int argc, _TCHAR* argv[]) { int n = Func1(); printf("Func1(): %d\n", n); getchar(); return 0; } For the main executable’s project, I also check that it has a dependency upon the static library: Finally, edit the main executable’s project properties. Under C/C++, General, set the Debug Information Format to ‘Disabled’: That’s pretty much it. Here’s the output of a Rebuild of the main executable: 1>------ Rebuild All started: Project: PdbTest01_Lib, Configuration: Release Win32 ------ 1>Deleting intermediate and output files for project 'PdbTest01_Lib', configuration 'Release|Win32' 1>Compiling... 1>stdafx.cpp 1>Compiling... 1>PdbTest01_Lib.cpp 1>Creating library... 1>Build log was saved at "file://d:\DEVELOP\Tinkering\PdbTest01_Lib\Release\BuildLog.htm" 1>PdbTest01_Lib - 0 error(s), 0 warning(s) 2>------ Rebuild All started: Project: PdbTest01, Configuration: Release Win32 ------ 2>Deleting intermediate and output files for project 'PdbTest01', configuration 'Release|Win32' 2>Compiling... 2>stdafx.cpp 2>Compiling... 2>PdbTest01.cpp 2>Linking... 2>Generating code 2>Finished generating code 2>Embedding manifest... 2>Build log was saved at "file://d:\DEVELOP\Tinkering\PdbTest01\Release\BuildLog.htm" 2>PdbTest01 - 0 error(s), 0 warning(s) ========== Rebuild All: 2 succeeded, 0 failed, 0 skipped ========== September 28 Enabling and Disabling a Network Adapter in Window XP
The quickest method to Enable or Disable a Network Adapter in Windows, other than simply unplugging the cable, is via the Network Properties. Here’s a quick Screencast: The easiest is by Right-Clicking the Network Connections Icon, and choosing Properties from the context menu. You can then select and/or Right-Click the entry for the particular Network Adapter you want to change, then choose the action from the Context Menu. eg Enable or Disable. You can also do this via Device Manager. The advantage of using Device Manager is that once you know how to Device Manager, you can do more than simply Enabling or Disabling the Network Adapter. For example, enable things like Wake On LAN, etc. But anyway, here are the equivalent Enabling and Disabling actions using Device Manager: April 13 Tinkering with STL #2 - Functors and examining the compiler output
All code show here will be compiled using the Professional version of Visual Studio 2005 with Service Pack 1 applied. Compiler version 14.00.50727.762. 1a. Static parameters passed to a Functor In the following code snippet, the integers a and b are statically set to 2 and 1, respectively: // 1a. Functor. int a=2, b=1; if ( std::greater<int>()(a, b) ) cout << "a is Greater then b." << endl; So at compile-time, the compiler should be able able to deduce that the condition (whether a is greater than b) is not going to change at runtime, and hopefully eliminate any conditional checks.
Here is the resulting assembly code, as seen within the Disassembly view in VS2005: // 1a. Functor.
int a=2, b=1;
if ( std::greater()(a, b) )
cout << "a is Greater then b." << endl;
1. 00401007 mov eax,dword ptr [__imp_std::endl (40204Ch)]
2. 0040100C push esi
3. 0040100D push eax
4. 0040100E push ecx
5. 0040100F mov ecx,dword ptr [__imp_std::cout (402044h)]
6. 00401015 push offset string "a is Greater then b." (402134h)
7. 0040101A push ecx
8. 0040101B call std::operator<< > (401210h)
9. 00401020 add esp,0Ch
10. 00401023 mov ecx,eax
11. 00401025 call dword ptr [__imp_std::basic_ostream >::operator<< (402048h)]
Wonderful. No conditional code, at all. Let's step through the assembly code just this once, so you can get a feel for what it's doing. (I added the line numbers above).
Next, I add a proper conditional by assigning the result of the rand function to b. // 1b. Functor. b = (rand() > RAND_MAX/2) ? 2 : 0; if ( std::greater<int>()(a, b) ) cout << "a is Greater then b." << endl; Here is the assembly code it produces: // 1b. Functor.
b = (rand() > RAND_MAX/2) ? 2 : 0;
1. 0040102B mov esi,dword ptr [__imp__rand (4020D0h)]
2. 00401031 call esi
3. 00401033 xor edx,edx
4. 00401035 cmp eax,3FFFh
5. 0040103A setle dl
6. 0040103D sub edx,1
7. 00401040 and edx,2
if ( std::greater()(a, b) )
8. 00401043 cmp edx,2
9. 00401046 jge main+6Bh (40106Bh)
cout << "a is Greater then b." << endl;
10. 00401048 mov eax,dword ptr [__imp_std::endl (402054h)]
11. 0040104D push eax
12. 0040104E push ecx
13. 0040104F mov ecx,dword ptr [__imp_std::cout (40204Ch)]
14. 00401055 push offset string "a is Greater then b." (402134h)
15. 0040105A push ecx
16. 0040105B call std::operator<< > (401240h)
17. 00401060 add esp,0Ch
18. 00401063 mov ecx,eax
19. 00401065 call dword ptr [__imp_std::basic_ostream >::operator<< (402050h)]
Notice how the code from line 10 onwards is almost identical to earlier. Also notice how it uses some creative mathematics to set b (edx register) in lines 3 through to 7. It's interesting enough, so I'll step though it.
Finally, I was interested to see how the compiler behaved if I modified the first code snippet by using a parameter that's been attributed with the volatile keyword. // 1c. Functor. volatile int v=1; if ( std::greater<int>()(a, (int)v) ) cout << "a is Greater then v." << endl; Here is the assembly code: // 1c. Functor.
volatile int v=1;
1. 0040106B mov dword ptr [esp+4],1
if ( std::greater()(a, (int)v) )
2. 00401073 cmp dword ptr [esp+4],2
3. 00401078 jge main+9Dh (40109Dh)
cout << "a is Greater then v." << endl;
4. 0040107A mov edx,dword ptr [__imp_std::endl (402054h)]
5. 00401080 mov eax,dword ptr [__imp_std::cout (40204Ch)]
6. 00401085 push edx
7. 00401086 push ecx
8. 00401087 push offset string "a is Greater then v." (40214Ch)
9. 0040108C push eax
10. 0040108D call std::operator<< > (401240h)
11. 00401092 add esp,0Ch
12. 00401095 mov ecx,eax
13. 00401097 call dword ptr [__imp_std::basic_ostream >::operator<< (402050h)]
Here we can see that v is given a real memory location, and that it does not optimise away the conditional. April 09 Tinkering with STL #1 - creating a Predicate usable by find_if on a vector of string (C++)This article has been completely rewritten since I first published it this morning, and posted my question on the Channel9 forums. So yesterday I was tinkering around with the Standard Template Library (STL), trying to learn better ‘generic’ practices. But ended up getting stuck trying to solve a problem that occurs when you try to create a Predicate of string::compare() - the adaptors end up trying to create a reference of a reference, and the Compiler effectively says, no, go away. OK, now some of you are probably saying: “Um, string ? Why are trying to use string::compare, just use the built-in operators. They have overloads”. Well, as tends to happen with these types of things, it started innocently enough, but was rooted in a stupid mistake. I was converting a Microsoft (ptr_fun) sample which used a vector of char pointers. I thought, that was too old-school, and modified it to use std::string instead. The problem was that I forgot to rename the #include <cstring> to <string>, as was kindly pointed out to me by Sven. Thanks Sven. This had the curious effect of not defining various parts of std::basic_string, such that Functors like equal_to failed to compile with complaints about operator==. Anyway, this lead to me trying to workaround the ‘missing’ operators by attempting to construct a suitable Predicate calling a member function, in this case string::compare(). Anyway, having been suitably embarrassed, I'm still curious about whether it can be done. Say, for example, because I need to use a Class that does define Iterators, but not a full compliment of operator overloads. So let's just start off with the definition of find_if, and then go into to some of the concepts behind what I'm trying to do. Having said that, I suppose I should point out that I'm not an Academic, so I'm probably going to mess up the terminology - but let's give it a crack, anyway... Here's the basic definition of find_if: template<class _InIt, class _Pr> inline _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred) { ... find_if uses two generic classes: an Input Iterator and a Predicate. OK, an Iterator is pretty easy to understand, but what is a Predicate ? Well in this context, it's a Function that is passed an “item” (dereferenced Iterator) and returns a boolean result. So what find_if does is iterate over a range that you specify via the _First and _Last Input Iterators, and it continues until it either reaches the end of the range, or the Predicate _Pred returns true. When I was first introduced to this algorithm, the predicate would usually be an ordinary C++ function call. That made it easy to understand, but from a practical point of view, a PITA to use. Functors int a=2, b=1; if ( std::greater<int>()(a, b) ) cout << "a is Greater than b." << endl; Notice how in the if statement, I have to explicitly specify the brackets () before the parameter list. That's in addition to explicitly specifying the “Type” Template parameter - <int> in this case. Binding A Binder basically allows you bind one of the parameters of a Function (or Functor), effectively changing a two parameter Function call into single parameter one: bind1st statically binds to the first parameter, and bind2nd with the second parameter. int c=2, d=1; std::binder1st<std::greater<int> > b1fn = bind1st(std::greater<int>(), c); if ( b1fn(d) ) // Equivalent to std::greater<int>()(c, d) cout << "c is Greater then d." << endl; Bringing it all together 1. & 2. After I setup v1, I print out each word using a for loop and Iterators. Next, I tried searching for the word “pearly” using various techniques. 3. Searching using find. Once I had the correct header included, it worked fine. 4. Using find_if and the equal_to Functor, adapted as a Predicate using bind2nd. 5. This is where I run into the reference to reference problem. I attempt to create a Predicate using mem_fun_ref and bind2nd., but I can't get it to compile:
From that point on, I tried breaking up the Predicate into it's various concepts, in the hopes of trying to locate where it was failing. 6. The first thing was trying to get mem_fun_ref working using a parameterless function. Nothing too spectacular here, though I chose to include the explicit call (6.3). 7. Finally, I try to get mem_fun_ref working using a single-parametered function - compare. You'll notice that I could not get the implicit call (7.2) to work. It fails with errors about not being able to deduce the template parameters - compare() has 6 overloads. This therefore means that you must use explicit calls, as shown with 7.3 and 7.4. All in all, it's been an interesting exercise. My original hopes of producing more easily consumed source code has quickly evaporated with the realisation that we must use an explicit call - trying to create a Predicate from a member function worsens the consumability, quite considerably. However, I'd still like to see whether the reference from reference issue can be solved, even though now it's just an academic one. The following code is for a console program: #include <vector> #include <algorithm> #include <functional> #include <string> #include <iostream> int main( ) { using namespace std; // 1. Setup and tinker with a vector of string. vector <std::string> v1; vector <std::string>::iterator Iter1, RIter; v1.push_back ( "Open" ); v1.push_back ( "up" ); v1.push_back ( "the" ); v1.push_back ( "pearly" ); v1.push_back ( "gates" ); // 2. Let's start off by printing out the original sequence. cout << "Original sequence contains: " ; for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ ) cout << Iter1->c_str() << " "; cout << endl; /////////////////////////////////////////////////////////////////////////// // Now lets try various ways of searching for "pearly" /////////////////////////////////////////////////////////////////////////// const string kSRCH("pearly"); // 3. use std::find RIter = std::find(v1.begin(), v1.end(), kSRCH ); if ( RIter != v1.end() ) cout << "using std::find ->" << *RIter << endl; // 4. use equal_to Functor for predicate. RIter = find_if( v1.begin(), v1.end(), bind2nd ( equal_to<string>(), kSRCH ) ); if ( RIter != v1.end() ) cout << "using std::find_if and equal_to Functor ->" << *RIter << endl; // 5. Now assume the object (std::string) doesn't have the appropriate operator // overloads, but does have a compare() member. DOES NOT COMPILE !. RIter = find_if( v1.begin(), v1.end(), bind2nd (mem_fun_ref<int, string, const string&>(&string::compare), string("pearly") ) ); if ( RIter != v1.end() ) cout << "using std::find_if and mem_func_ref ->" << *RIter << endl; // 6. OK, the above fails. So lets break the above predicate down, and see // what we can get to compile. Well start with a parameterless member // function (method) call. string::size(). size_t z = v1[0].size(); // 6.1 Simulate an iteration, where an item is passed in. z = mem_fun_ref(&string::size)(v1[0]); // 6.2 implicit. z = mem_fun_ref<string::size_type, string>(&string::size)(v1[0]); // 6.3 explicit. // 7. Now let's try single parametered member function (method) function. // string::compare(). v1[0].compare(kSRCH); // 7.1 Simulate a single iteration, again. mem_fun_ref(&string::compare)(v1[0], kSRCH); // 7.2 Doesn't compile: can't deduce template argument. mem_fun_ref<int, string, const string&>(&string::compare)(v1[0], "pearly" ); // 7.3 explicit 1 mem_fun_ref<int, string, const string&>(&string::compare)(v1[0], kSRCH ); // 7.4 explicit 2 // Done. getchar(); } Just to add another data point, I tried compiling this under Ubuntu Linux 7.10 with GCC 4.1.3, and it fails as well (manually edited by me): March 22 Copying Table Row text using Word VBA
Note that you need to show the Control Toolbox in order to place the CommandButtons, and to switch in and out of Design Mode. Word's Macro Language is a form of Visual Basic known as Visual Basic for Applications (VBA). But VBA doesn't support what's know as Control Arrays in Visual Basic proper. So instead, each of the CommandButtons shown above need to have their own click-event procedure. Indeed, you can't even override the default procedure name. So rather than repeating, or hard-coding specifics into each of these procedures, it's better to try and tease-out the functionality and place it into a 'Generic' procedure instead - and that's what I've done here. There are eight CommandButtons in this Document. But the functionality of retrieving the text from each cell within that row lives in a procedure that I named GetTableText. Thus the only thing in the CommandButton's click-event procedure is a call to GetTableText, and nothing else. This makes it easy to add new tables, rows and columns - new buttons simply need to call the GetTableText procedure, and it takes care of the rest. Here's the code: Private Sub GetTableText() If Not Selection.Information(wdWithInTable) Then Exit Sub 'Get Column and Row of cell containing the button that launched this event. Dim c As Long, r As Long c = CLng(Selection.Information(wdStartOfRangeColumnNumber)) r = CLng(Selection.Information(wdStartOfRangeRowNumber)) 'Get all text from each cell in this row, bar the current cell. Dim cels As Cells, i As Long, s As String cels = Selection.Range.Tables(1).Rows(r).Cells For i = 1 To c - 1 s = s & StripJunk(cels(i).Range.Text) & vbTab Next s = Left(s, Len(s) - 1) MsgBox("|" & s & "|") End Sub Private Function StripJunk(ByVal s As String) StripJunk = Trim(Replace(s, vbCr & Chr(7), "")) End Function Private Sub CommandButton1_Click() GetTableText() End Sub Private Sub CommandButton2_Click() GetTableText() End Sub Private Sub CommandButton3_Click() GetTableText() End Sub Private Sub CommandButton4_Click() GetTableText() End Sub Private Sub CommandButton5_Click() GetTableText() End Sub Private Sub CommandButton6_Click() GetTableText() End Sub Private Sub CommandButton7_Click() GetTableText() End Sub Private Sub CommandButton8_Click() GetTableText() End Sub So how does this work ? If Macros are enabled, and your not in Design mode, when you click one of the CommandButtons, it first selects the button, then calls any event procedures associated with the control. In this case, we have procedures for the click event, and each of these simply call the GetTableText procedure - in this case a Sub (Subroutine). The GetTableText subroutine takes advantage of the fact that the Selection object changes with the act of clicking the CommandButton. The first thing, though, is that it checks that the current Selection is indeed within a Table - the very first If statement. The next block of code recovers the row and column information of the current table cell, which is the cell where the CommandButton has been placed. The third block of code recovers all the cells of the appropriate row of the the current table. It then iterates through each of the cells up until the column where the CommandButton was, recovering their text, and building up a string in the s variable. The text from each cell is separated with a tab character, and the StripJunk function is used to remove extraneous characters that are part of Word's housekeeping for table text. Finally, the string is cleaned up (the last tab character stripped off), and the string is shown via a Message box. Additionally, I've also wrapped the Message box text with '|' characters, just to ensure that I am indeed cleaning up the string:
In the picture above, note that I've modified the last table by adding an extra column to the right of the CommandButtons. I did this to highlight the fact that the GetTableText subroutine only copies the text from the cells to the left of the cell which contains the CommandButton. In the picture, I clicked the CommandButton in the second row of the last table. Notice that the Message box only shows the text from columns 1 through to 4, and nothing from columns 5 and 6. |
||||
|
|